22
22
import tech .pegasys .teku .api .AbstractSelectorFactory ;
23
23
import tech .pegasys .teku .infrastructure .async .SafeFuture ;
24
24
import tech .pegasys .teku .infrastructure .unsigned .UInt64 ;
25
+ import tech .pegasys .teku .spec .Spec ;
25
26
import tech .pegasys .teku .spec .datastructures .blobs .versions .deneb .BlobSidecar ;
26
27
import tech .pegasys .teku .spec .datastructures .blocks .SignedBeaconBlock ;
27
28
import tech .pegasys .teku .spec .datastructures .blocks .SlotAndBlockRoot ;
28
29
import tech .pegasys .teku .spec .datastructures .blocks .blockbody .versions .deneb .BeaconBlockBodyDeneb ;
30
+ import tech .pegasys .teku .spec .datastructures .metadata .BlobSidecarsAndMetaData ;
31
+ import tech .pegasys .teku .storage .client .ChainHead ;
29
32
import tech .pegasys .teku .storage .client .CombinedChainDataClient ;
30
33
31
34
public class BlobSidecarSelectorFactory extends AbstractSelectorFactory <BlobSidecarSelector > {
32
35
33
- public BlobSidecarSelectorFactory (final CombinedChainDataClient client ) {
36
+ private final Spec spec ;
37
+
38
+ public BlobSidecarSelectorFactory (final Spec spec , final CombinedChainDataClient client ) {
34
39
super (client );
40
+ this .spec = spec ;
35
41
}
36
42
37
43
@ Override
@@ -44,11 +50,23 @@ public BlobSidecarSelector blockRootSelector(final Bytes32 blockRoot) {
44
50
if (maybeSlot .isPresent ()) {
45
51
final SlotAndBlockRoot slotAndBlockRoot =
46
52
new SlotAndBlockRoot (maybeSlot .get (), blockRoot );
47
- return getBlobSidecars (slotAndBlockRoot , indices );
53
+ return getBlobSidecars (slotAndBlockRoot , indices )
54
+ .thenApply (blobSidecars -> addMetaData (blobSidecars , slotAndBlockRoot ));
48
55
}
49
56
return client
50
57
.getBlockByBlockRoot (blockRoot )
51
- .thenCompose (maybeBlock -> getBlobSidecarsForBlock (maybeBlock , indices ));
58
+ .thenCompose (
59
+ maybeBlock -> {
60
+ if (maybeBlock .isEmpty ()) {
61
+ return SafeFuture .completedFuture (Optional .empty ());
62
+ }
63
+ final SignedBeaconBlock block = maybeBlock .get ();
64
+ final SlotAndBlockRoot slotAndBlockRoot =
65
+ new SlotAndBlockRoot (block .getSlot (), blockRoot );
66
+ return getBlobSidecarsForBlock (maybeBlock , indices )
67
+ .thenApply (
68
+ blobSidecars -> addMetaData (blobSidecars , slotAndBlockRoot ));
69
+ });
52
70
});
53
71
}
54
72
@@ -57,7 +75,13 @@ public BlobSidecarSelector headSelector() {
57
75
return indices ->
58
76
client
59
77
.getChainHead ()
60
- .map (head -> getBlobSidecars (head .getSlotAndBlockRoot (), indices ))
78
+ .map (
79
+ head ->
80
+ getBlobSidecars (head .getSlotAndBlockRoot (), indices )
81
+ .thenApply (
82
+ blobSideCars ->
83
+ addMetaData (
84
+ blobSideCars , head .getSlotAndBlockRoot (), head .isOptimistic ())))
61
85
.orElse (SafeFuture .completedFuture (Optional .empty ()));
62
86
}
63
87
@@ -66,27 +90,58 @@ public BlobSidecarSelector genesisSelector() {
66
90
return indices ->
67
91
client
68
92
.getBlockAtSlotExact (GENESIS_SLOT )
69
- .thenCompose (maybeGenesisBlock -> getBlobSidecarsForBlock (maybeGenesisBlock , indices ));
93
+ .thenCompose (
94
+ maybeGenesisBlock ->
95
+ getBlobSidecarsForBlock (maybeGenesisBlock , indices )
96
+ .thenApply (
97
+ blobSidecars ->
98
+ addMetaData (
99
+ blobSidecars ,
100
+ GENESIS_SLOT ,
101
+ false ,
102
+ true ,
103
+ client .isFinalized (GENESIS_SLOT ))));
70
104
}
71
105
72
106
@ Override
73
107
public BlobSidecarSelector finalizedSelector () {
74
108
return indices ->
75
109
client
76
110
.getLatestFinalized ()
77
- .map (anchorPoint -> getBlobSidecars (anchorPoint .getSlotAndBlockRoot (), indices ))
111
+ .map (
112
+ anchorPoint ->
113
+ getBlobSidecars (anchorPoint .getSlotAndBlockRoot (), indices )
114
+ .thenApply (
115
+ blobSideCars ->
116
+ addMetaData (
117
+ blobSideCars ,
118
+ anchorPoint .getSlotAndBlockRoot (),
119
+ client .isChainHeadOptimistic ())))
78
120
.orElse (SafeFuture .completedFuture (Optional .empty ()));
79
121
}
80
122
81
123
@ Override
82
124
public BlobSidecarSelector slotSelector (final UInt64 slot ) {
83
125
return indices -> {
84
126
if (client .isFinalized (slot )) {
85
- return getBlobSidecars (slot , indices );
127
+ return getBlobSidecars (slot , indices )
128
+ .thenApply (
129
+ blobSidecars ->
130
+ addMetaData (blobSidecars , slot , client .isChainHeadOptimistic (), true , true ));
86
131
}
87
132
return client
88
133
.getBlockAtSlotExact (slot )
89
- .thenCompose (maybeBlock -> getBlobSidecarsForBlock (maybeBlock , indices ));
134
+ .thenCompose (
135
+ maybeBlock ->
136
+ getBlobSidecarsForBlock (maybeBlock , indices )
137
+ .thenApply (
138
+ blobSidecars ->
139
+ addMetaData (
140
+ blobSidecars ,
141
+ slot ,
142
+ client .isChainHeadOptimistic (),
143
+ false ,
144
+ client .isFinalized (slot ))));
90
145
};
91
146
}
92
147
@@ -96,7 +151,12 @@ public BlobSidecarSelector slotSelectorForAll(final UInt64 slot) {
96
151
.getAllBlobSidecars (slot , indices )
97
152
.thenApply (
98
153
blobSidecars ->
99
- blobSidecars .isEmpty () ? Optional .empty () : Optional .of (blobSidecars ));
154
+ blobSidecars .isEmpty ()
155
+ ? Optional .empty ()
156
+ : addMetaData (
157
+ // We don't care about metadata since the api (teku only) that
158
+ // consumes the return value doesn't use it
159
+ Optional .of (blobSidecars ), new SlotAndBlockRoot (slot , Bytes32 .ZERO )));
100
160
}
101
161
102
162
private SafeFuture <Optional <List <BlobSidecar >>> getBlobSidecarsForBlock (
@@ -125,4 +185,60 @@ private SafeFuture<Optional<List<BlobSidecar>>> getBlobSidecars(
125
185
final UInt64 slot , final List <UInt64 > indices ) {
126
186
return client .getBlobSidecars (slot , indices ).thenApply (Optional ::of );
127
187
}
188
+
189
+ private Optional <BlobSidecarsAndMetaData > addMetaData (
190
+ final Optional <List <BlobSidecar >> maybeBlobSidecarList ,
191
+ final SlotAndBlockRoot slotAndBlockRoot ) {
192
+ if (maybeBlobSidecarList .isEmpty ()) {
193
+ return Optional .empty ();
194
+ }
195
+
196
+ final UInt64 slot = slotAndBlockRoot .getSlot ();
197
+ final Bytes32 blockRoot = slotAndBlockRoot .getBlockRoot ();
198
+ final Optional <ChainHead > maybeChainHead = client .getChainHead ();
199
+ final boolean isFinalized = client .isFinalized (slot );
200
+ boolean isOptimistic ;
201
+ boolean isCanonical = false ;
202
+
203
+ if (maybeChainHead .isPresent ()) {
204
+ ChainHead chainHead = maybeChainHead .get ();
205
+ isOptimistic = chainHead .isOptimistic () || client .isOptimisticBlock (blockRoot );
206
+ isCanonical = client .isCanonicalBlock (slot , blockRoot , chainHead .getRoot ());
207
+ } else {
208
+ // If there's no chain head, we assume the block is not optimistic and not canonical
209
+ isOptimistic = client .isOptimisticBlock (blockRoot );
210
+ }
211
+ return addMetaData (maybeBlobSidecarList , slot , isOptimistic , isCanonical , isFinalized );
212
+ }
213
+
214
+ private Optional <BlobSidecarsAndMetaData > addMetaData (
215
+ final Optional <List <BlobSidecar >> maybeBlobSidecarList ,
216
+ final SlotAndBlockRoot slotAndBlockRoot ,
217
+ final boolean isOptimistic ) {
218
+ if (maybeBlobSidecarList .isEmpty ()) {
219
+ return Optional .empty ();
220
+ }
221
+ return addMetaData (
222
+ maybeBlobSidecarList ,
223
+ slotAndBlockRoot .getSlot (),
224
+ isOptimistic ,
225
+ true ,
226
+ client .isFinalized (slotAndBlockRoot .getSlot ()));
227
+ }
228
+
229
+ private Optional <BlobSidecarsAndMetaData > addMetaData (
230
+ final Optional <List <BlobSidecar >> maybeBlobSidecarList ,
231
+ final UInt64 blockSlot ,
232
+ final boolean executionOptimistic ,
233
+ final boolean canonical ,
234
+ final boolean finalized ) {
235
+ return maybeBlobSidecarList .map (
236
+ blobSidecarList ->
237
+ new BlobSidecarsAndMetaData (
238
+ blobSidecarList ,
239
+ spec .atSlot (blockSlot ).getMilestone (),
240
+ executionOptimistic ,
241
+ canonical ,
242
+ finalized ));
243
+ }
128
244
}
0 commit comments