@@ -18,7 +18,6 @@ package catalyst
18
18
19
19
import (
20
20
"errors"
21
- "fmt"
22
21
"sync"
23
22
"time"
24
23
@@ -144,40 +143,49 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
144
143
feeRecipient := c .feeRecipient
145
144
c .feeRecipientLock .Unlock ()
146
145
146
+ // Reset to CurrentBlock in case of the chain was rewound
147
+ if header := c .eth .BlockChain ().CurrentBlock (); c .curForkchoiceState .HeadBlockHash != header .Hash () {
148
+ finalizedHash := c .finalizedBlockHash (header .Number .Uint64 ())
149
+ c .setCurrentState (header .Hash (), * finalizedHash )
150
+ }
151
+
147
152
fcResponse , err := c .engineAPI .ForkchoiceUpdatedV2 (c .curForkchoiceState , & engine.PayloadAttributes {
148
153
Timestamp : tstamp ,
149
154
SuggestedFeeRecipient : feeRecipient ,
150
155
Withdrawals : withdrawals ,
151
156
})
152
157
if err != nil {
153
- return fmt .Errorf ("error calling forkchoice update: %v" , err )
158
+ return err
159
+ }
160
+ if fcResponse == engine .STATUS_SYNCING {
161
+ return errors .New ("chain rewind prevented invocation of payload creation" )
154
162
}
155
163
156
164
envelope , err := c .engineAPI .getPayload (* fcResponse .PayloadID , true )
157
165
if err != nil {
158
- return fmt . Errorf ( "error retrieving payload: %v" , err )
166
+ return err
159
167
}
160
168
payload := envelope .ExecutionPayload
161
169
162
170
var finalizedHash common.Hash
163
171
if payload .Number % devEpochLength == 0 {
164
172
finalizedHash = payload .BlockHash
165
173
} else {
166
- finalizedHash = c .eth .BlockChain ().GetBlockByNumber ((payload .Number - 1 ) / devEpochLength * devEpochLength ).Hash ()
174
+ if fh := c .finalizedBlockHash (payload .Number ); fh == nil {
175
+ return errors .New ("chain rewind interrupted calculation of finalized block hash" )
176
+ } else {
177
+ finalizedHash = * fh
178
+ }
167
179
}
168
180
169
- // mark the payload as canon
181
+ // Mark the payload as canon
170
182
if _ , err = c .engineAPI .NewPayloadV2 (* payload ); err != nil {
171
- return fmt .Errorf ("failed to mark payload as canonical: %v" , err )
172
- }
173
- c .curForkchoiceState = engine.ForkchoiceStateV1 {
174
- HeadBlockHash : payload .BlockHash ,
175
- SafeBlockHash : payload .BlockHash ,
176
- FinalizedBlockHash : finalizedHash ,
183
+ return err
177
184
}
178
- // mark the block containing the payload as canonical
185
+ c .setCurrentState (payload .BlockHash , finalizedHash )
186
+ // Mark the block containing the payload as canonical
179
187
if _ , err = c .engineAPI .ForkchoiceUpdatedV2 (c .curForkchoiceState , nil ); err != nil {
180
- return fmt . Errorf ( "failed to mark block as canonical: %v" , err )
188
+ return err
181
189
}
182
190
c .lastBlockTime = payload .Timestamp
183
191
return nil
@@ -198,20 +206,18 @@ func (c *SimulatedBeacon) loopOnDemand() {
198
206
case w := <- c .withdrawals .pending :
199
207
withdrawals := append (c .withdrawals .gatherPending (9 ), w )
200
208
if err := c .sealBlock (withdrawals ); err != nil {
201
- log .Error ("Error performing sealing-work" , "err" , err )
202
- return
209
+ log .Warn ("Error performing sealing work" , "err" , err )
203
210
}
204
211
case <- newTxs :
205
212
withdrawals := c .withdrawals .gatherPending (10 )
206
213
if err := c .sealBlock (withdrawals ); err != nil {
207
- log .Error ("Error performing sealing-work" , "err" , err )
208
- return
214
+ log .Warn ("Error performing sealing work" , "err" , err )
209
215
}
210
216
}
211
217
}
212
218
}
213
219
214
- // loopOnDemand runs the block production loop for non-zero period configuration
220
+ // loop runs the block production loop for non-zero period configuration
215
221
func (c * SimulatedBeacon ) loop () {
216
222
timer := time .NewTimer (0 )
217
223
for {
@@ -221,14 +227,40 @@ func (c *SimulatedBeacon) loop() {
221
227
case <- timer .C :
222
228
withdrawals := c .withdrawals .gatherPending (10 )
223
229
if err := c .sealBlock (withdrawals ); err != nil {
224
- log .Error ("Error performing sealing-work" , "err" , err )
225
- return
230
+ log .Warn ("Error performing sealing work" , "err" , err )
231
+ } else {
232
+ timer .Reset (time .Second * time .Duration (c .period ))
226
233
}
227
- timer .Reset (time .Second * time .Duration (c .period ))
228
234
}
229
235
}
230
236
}
231
237
238
+ // finalizedBlockHash returns the block hash of the finalized block corresponding to the given number
239
+ // or nil if doesn't exist in the chain.
240
+ func (c * SimulatedBeacon ) finalizedBlockHash (number uint64 ) * common.Hash {
241
+ var finalizedNumber uint64
242
+ if number % devEpochLength == 0 {
243
+ finalizedNumber = number
244
+ } else {
245
+ finalizedNumber = (number - 1 ) / devEpochLength * devEpochLength
246
+ }
247
+
248
+ if finalizedBlock := c .eth .BlockChain ().GetBlockByNumber (finalizedNumber ); finalizedBlock != nil {
249
+ fh := finalizedBlock .Hash ()
250
+ return & fh
251
+ }
252
+ return nil
253
+ }
254
+
255
+ // setCurrentState sets the current forkchoice state
256
+ func (c * SimulatedBeacon ) setCurrentState (headHash , finalizedHash common.Hash ) {
257
+ c .curForkchoiceState = engine.ForkchoiceStateV1 {
258
+ HeadBlockHash : headHash ,
259
+ SafeBlockHash : headHash ,
260
+ FinalizedBlockHash : finalizedHash ,
261
+ }
262
+ }
263
+
232
264
func RegisterSimulatedBeaconAPIs (stack * node.Node , sim * SimulatedBeacon ) {
233
265
stack .RegisterAPIs ([]rpc.API {
234
266
{
0 commit comments