@@ -62,10 +62,7 @@ func (s *Service) BuildBlockAndSidecars(
6262 // and safe block hashes to the execution client.
6363 st := s .sb .StateFromContext (ctx )
6464
65- // we introduce hard forks with the expectation that the height set for the
66- // hard fork is the first height at which new rules apply. So we need to make
67- // sure that when building blocks, we pick the right height. blkSlots is the
68- // height for the next block, which consensus is requesting BeaconKit to build.
65+ // blkSlot is the height for the next block, which consensus is requesting BeaconKit to build.
6966 blkSlot := slotData .GetSlot ()
7067
7168 // Prepare the state such that it is ready to build a block for
@@ -74,29 +71,44 @@ func (s *Service) BuildBlockAndSidecars(
7471 return nil , nil , err
7572 }
7673
77- // Build forkdata used for the signing root of the reveal and the sidecars
78- forkData , err := s .buildForkData (st , blkSlot )
74+ // Grab parent block root for payload request.
75+ parentBlockRoot , err := st .GetBlockRootAtIndex (
76+ (blkSlot .Unwrap () - 1 ) % s .chainSpec .SlotsPerHistoricalRoot (),
77+ )
7978 if err != nil {
8079 return nil , nil , err
8180 }
8281
83- // Build the reveal for the current slot.
84- // TODO: We can optimize to pre-compute this in parallel?
85- reveal , err := s .buildRandaoReveal (forkData , blkSlot )
82+ // Get the payload for the block.
83+ envelope , err := s .retrieveExecutionPayload (ctx , st , parentBlockRoot , slotData )
84+ if err != nil {
85+ return nil , nil , fmt .Errorf ("failed retrieving execution payload: %w" , err )
86+ }
87+
88+ // We introduce hard forks with the expectation that the first block proposed after the
89+ // hard fork timestamp is when new rules apply. When building blocks, we provide the Execution
90+ // Layer client with a timestamp, and it will create its payload based on that timestamp. We
91+ // must use this same timestamp from the payload to build the beacon block. This ensures that
92+ // we are building on the same fork version as the Execution Layer.
93+ timestamp := envelope .GetExecutionPayload ().GetTimestamp ()
94+
95+ // Build forkdata used for the signing root of the reveal and the sidecars
96+ forkData , err := s .buildForkData (st , timestamp )
8697 if err != nil {
8798 return nil , nil , err
8899 }
89100
90101 // Create a new empty block from the current state.
91- blk , err := s .getEmptyBeaconBlockForSlot (st , blkSlot )
102+ blk , err := s .getEmptyBeaconBlockForSlot (st , blkSlot , forkData . CurrentVersion , parentBlockRoot )
92103 if err != nil {
93104 return nil , nil , err
94105 }
95106
96- // Get the payload for the block.
97- envelope , err := s .retrieveExecutionPayload (ctx , st , blk , slotData )
107+ // Build the reveal for the current slot.
108+ // TODO: We can optimize to pre-compute this in parallel?
109+ reveal , err := s .buildRandaoReveal (forkData , blkSlot )
98110 if err != nil {
99- return nil , nil , fmt . Errorf ( "failed retrieving execution payload: %w" , err )
111+ return nil , nil , err
100112 }
101113
102114 // We have to assemble the block body prior to producing the sidecars
@@ -150,15 +162,8 @@ func (s *Service) BuildBlockAndSidecars(
150162// getEmptyBeaconBlockForSlot creates a new empty block.
151163func (s * Service ) getEmptyBeaconBlockForSlot (
152164 st * statedb.StateDB , requestedSlot math.Slot ,
165+ forkVersion common.Version , parentBlockRoot common.Root ,
153166) (* ctypes.BeaconBlock , error ) {
154- // Create a new block.
155- parentBlockRoot , err := st .GetBlockRootAtIndex (
156- (requestedSlot .Unwrap () - 1 ) % s .chainSpec .SlotsPerHistoricalRoot (),
157- )
158- if err != nil {
159- return nil , err
160- }
161-
162167 // Get the proposer index for the slot.
163168 proposerIndex , err := st .ValidatorIndexByPubkey (
164169 s .signer .PublicKey (),
@@ -167,22 +172,23 @@ func (s *Service) getEmptyBeaconBlockForSlot(
167172 return nil , err
168173 }
169174
175+ // Create a new block.
170176 return ctypes .NewBeaconBlockWithVersion (
171177 requestedSlot ,
172178 proposerIndex ,
173179 parentBlockRoot ,
174- s . chainSpec . ActiveForkVersionForSlot ( requestedSlot ) ,
180+ forkVersion ,
175181 )
176182}
177183
178- func (s * Service ) buildForkData (st * statedb.StateDB , slot math.Slot ) (* ctypes.ForkData , error ) {
184+ func (s * Service ) buildForkData (st * statedb.StateDB , timestamp math.U64 ) (* ctypes.ForkData , error ) {
179185 genesisValidatorsRoot , err := st .GetGenesisValidatorsRoot ()
180186 if err != nil {
181187 return nil , err
182188 }
183189
184190 return ctypes .NewForkData (
185- s .chainSpec .ActiveForkVersionForSlot ( slot ),
191+ s .chainSpec .ActiveForkVersionForTimestamp ( timestamp ),
186192 genesisValidatorsRoot ,
187193 ), nil
188194}
@@ -206,7 +212,7 @@ func (s *Service) buildRandaoReveal(
206212func (s * Service ) retrieveExecutionPayload (
207213 ctx context.Context ,
208214 st * statedb.StateDB ,
209- blk * ctypes. BeaconBlock ,
215+ parentBlockRoot common. Root ,
210216 slotData * types.SlotData ,
211217) (ctypes.BuiltExecutionPayloadEnv , error ) {
212218 //
@@ -215,8 +221,8 @@ func (s *Service) retrieveExecutionPayload(
215221 // Get the payload for the block.
216222 envelope , err := s .localPayloadBuilder .RetrievePayload (
217223 ctx ,
218- blk .GetSlot (),
219- blk . GetParentBlockRoot () ,
224+ slotData .GetSlot (),
225+ parentBlockRoot ,
220226 )
221227 if err == nil {
222228 return envelope , nil
@@ -232,7 +238,7 @@ func (s *Service) retrieveExecutionPayload(
232238 // this less confusing.
233239
234240 s .metrics .failedToRetrievePayload (
235- blk .GetSlot (),
241+ slotData .GetSlot (),
236242 err ,
237243 )
238244
@@ -246,13 +252,13 @@ func (s *Service) retrieveExecutionPayload(
246252 return s .localPayloadBuilder .RequestPayloadSync (
247253 ctx ,
248254 st ,
249- blk .GetSlot (),
255+ slotData .GetSlot (),
250256 payloadtime .Next (
251257 slotData .GetConsensusTime (),
252258 lph .GetTimestamp (),
253259 false , // buildOptimistically
254- ). Unwrap () ,
255- blk . GetParentBlockRoot () ,
260+ ),
261+ parentBlockRoot ,
256262 lph .GetBlockHash (),
257263 lph .GetParentHash (),
258264 )
0 commit comments