Skip to content

Commit cde462c

Browse files
jsvisajwasinger
andauthored
eth/catalyst: reset to current header if chain is rewound (in dev mode) (#27992)
Signed-off-by: jsvisa <[email protected]> Co-authored-by: Jared Wasinger <[email protected]>
1 parent 9bbb9df commit cde462c

File tree

1 file changed

+53
-21
lines changed

1 file changed

+53
-21
lines changed

eth/catalyst/simulated_beacon.go

+53-21
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package catalyst
1818

1919
import (
2020
"errors"
21-
"fmt"
2221
"sync"
2322
"time"
2423

@@ -144,40 +143,49 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
144143
feeRecipient := c.feeRecipient
145144
c.feeRecipientLock.Unlock()
146145

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+
147152
fcResponse, err := c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, &engine.PayloadAttributes{
148153
Timestamp: tstamp,
149154
SuggestedFeeRecipient: feeRecipient,
150155
Withdrawals: withdrawals,
151156
})
152157
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")
154162
}
155163

156164
envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true)
157165
if err != nil {
158-
return fmt.Errorf("error retrieving payload: %v", err)
166+
return err
159167
}
160168
payload := envelope.ExecutionPayload
161169

162170
var finalizedHash common.Hash
163171
if payload.Number%devEpochLength == 0 {
164172
finalizedHash = payload.BlockHash
165173
} 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+
}
167179
}
168180

169-
// mark the payload as canon
181+
// Mark the payload as canon
170182
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
177184
}
178-
// mark the block containing the payload as canonical
185+
c.setCurrentState(payload.BlockHash, finalizedHash)
186+
// Mark the block containing the payload as canonical
179187
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
181189
}
182190
c.lastBlockTime = payload.Timestamp
183191
return nil
@@ -198,20 +206,18 @@ func (c *SimulatedBeacon) loopOnDemand() {
198206
case w := <-c.withdrawals.pending:
199207
withdrawals := append(c.withdrawals.gatherPending(9), w)
200208
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)
203210
}
204211
case <-newTxs:
205212
withdrawals := c.withdrawals.gatherPending(10)
206213
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)
209215
}
210216
}
211217
}
212218
}
213219

214-
// loopOnDemand runs the block production loop for non-zero period configuration
220+
// loop runs the block production loop for non-zero period configuration
215221
func (c *SimulatedBeacon) loop() {
216222
timer := time.NewTimer(0)
217223
for {
@@ -221,14 +227,40 @@ func (c *SimulatedBeacon) loop() {
221227
case <-timer.C:
222228
withdrawals := c.withdrawals.gatherPending(10)
223229
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))
226233
}
227-
timer.Reset(time.Second * time.Duration(c.period))
228234
}
229235
}
230236
}
231237

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+
232264
func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
233265
stack.RegisterAPIs([]rpc.API{
234266
{

0 commit comments

Comments
 (0)