eth/catalyst: reset to current header if chain is rewound (in dev mode) (#27992)
Signed-off-by: jsvisa <delweng@gmail.com> Co-authored-by: Jared Wasinger <j-wasinger@hotmail.com>
This commit is contained in:
parent
9bbb9df185
commit
cde462c6bf
@ -18,7 +18,6 @@ package catalyst
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -144,18 +143,27 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
|
|||||||
feeRecipient := c.feeRecipient
|
feeRecipient := c.feeRecipient
|
||||||
c.feeRecipientLock.Unlock()
|
c.feeRecipientLock.Unlock()
|
||||||
|
|
||||||
|
// Reset to CurrentBlock in case of the chain was rewound
|
||||||
|
if header := c.eth.BlockChain().CurrentBlock(); c.curForkchoiceState.HeadBlockHash != header.Hash() {
|
||||||
|
finalizedHash := c.finalizedBlockHash(header.Number.Uint64())
|
||||||
|
c.setCurrentState(header.Hash(), *finalizedHash)
|
||||||
|
}
|
||||||
|
|
||||||
fcResponse, err := c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, &engine.PayloadAttributes{
|
fcResponse, err := c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, &engine.PayloadAttributes{
|
||||||
Timestamp: tstamp,
|
Timestamp: tstamp,
|
||||||
SuggestedFeeRecipient: feeRecipient,
|
SuggestedFeeRecipient: feeRecipient,
|
||||||
Withdrawals: withdrawals,
|
Withdrawals: withdrawals,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error calling forkchoice update: %v", err)
|
return err
|
||||||
|
}
|
||||||
|
if fcResponse == engine.STATUS_SYNCING {
|
||||||
|
return errors.New("chain rewind prevented invocation of payload creation")
|
||||||
}
|
}
|
||||||
|
|
||||||
envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true)
|
envelope, err := c.engineAPI.getPayload(*fcResponse.PayloadID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error retrieving payload: %v", err)
|
return err
|
||||||
}
|
}
|
||||||
payload := envelope.ExecutionPayload
|
payload := envelope.ExecutionPayload
|
||||||
|
|
||||||
@ -163,21 +171,21 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal) error {
|
|||||||
if payload.Number%devEpochLength == 0 {
|
if payload.Number%devEpochLength == 0 {
|
||||||
finalizedHash = payload.BlockHash
|
finalizedHash = payload.BlockHash
|
||||||
} else {
|
} else {
|
||||||
finalizedHash = c.eth.BlockChain().GetBlockByNumber((payload.Number - 1) / devEpochLength * devEpochLength).Hash()
|
if fh := c.finalizedBlockHash(payload.Number); fh == nil {
|
||||||
|
return errors.New("chain rewind interrupted calculation of finalized block hash")
|
||||||
|
} else {
|
||||||
|
finalizedHash = *fh
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark the payload as canon
|
// Mark the payload as canon
|
||||||
if _, err = c.engineAPI.NewPayloadV2(*payload); err != nil {
|
if _, err = c.engineAPI.NewPayloadV2(*payload); err != nil {
|
||||||
return fmt.Errorf("failed to mark payload as canonical: %v", err)
|
return err
|
||||||
}
|
}
|
||||||
c.curForkchoiceState = engine.ForkchoiceStateV1{
|
c.setCurrentState(payload.BlockHash, finalizedHash)
|
||||||
HeadBlockHash: payload.BlockHash,
|
// Mark the block containing the payload as canonical
|
||||||
SafeBlockHash: payload.BlockHash,
|
|
||||||
FinalizedBlockHash: finalizedHash,
|
|
||||||
}
|
|
||||||
// mark the block containing the payload as canonical
|
|
||||||
if _, err = c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, nil); err != nil {
|
if _, err = c.engineAPI.ForkchoiceUpdatedV2(c.curForkchoiceState, nil); err != nil {
|
||||||
return fmt.Errorf("failed to mark block as canonical: %v", err)
|
return err
|
||||||
}
|
}
|
||||||
c.lastBlockTime = payload.Timestamp
|
c.lastBlockTime = payload.Timestamp
|
||||||
return nil
|
return nil
|
||||||
@ -198,20 +206,18 @@ func (c *SimulatedBeacon) loopOnDemand() {
|
|||||||
case w := <-c.withdrawals.pending:
|
case w := <-c.withdrawals.pending:
|
||||||
withdrawals := append(c.withdrawals.gatherPending(9), w)
|
withdrawals := append(c.withdrawals.gatherPending(9), w)
|
||||||
if err := c.sealBlock(withdrawals); err != nil {
|
if err := c.sealBlock(withdrawals); err != nil {
|
||||||
log.Error("Error performing sealing-work", "err", err)
|
log.Warn("Error performing sealing work", "err", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
case <-newTxs:
|
case <-newTxs:
|
||||||
withdrawals := c.withdrawals.gatherPending(10)
|
withdrawals := c.withdrawals.gatherPending(10)
|
||||||
if err := c.sealBlock(withdrawals); err != nil {
|
if err := c.sealBlock(withdrawals); err != nil {
|
||||||
log.Error("Error performing sealing-work", "err", err)
|
log.Warn("Error performing sealing work", "err", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loopOnDemand runs the block production loop for non-zero period configuration
|
// loop runs the block production loop for non-zero period configuration
|
||||||
func (c *SimulatedBeacon) loop() {
|
func (c *SimulatedBeacon) loop() {
|
||||||
timer := time.NewTimer(0)
|
timer := time.NewTimer(0)
|
||||||
for {
|
for {
|
||||||
@ -221,13 +227,39 @@ func (c *SimulatedBeacon) loop() {
|
|||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
withdrawals := c.withdrawals.gatherPending(10)
|
withdrawals := c.withdrawals.gatherPending(10)
|
||||||
if err := c.sealBlock(withdrawals); err != nil {
|
if err := c.sealBlock(withdrawals); err != nil {
|
||||||
log.Error("Error performing sealing-work", "err", err)
|
log.Warn("Error performing sealing work", "err", err)
|
||||||
return
|
} else {
|
||||||
}
|
|
||||||
timer.Reset(time.Second * time.Duration(c.period))
|
timer.Reset(time.Second * time.Duration(c.period))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finalizedBlockHash returns the block hash of the finalized block corresponding to the given number
|
||||||
|
// or nil if doesn't exist in the chain.
|
||||||
|
func (c *SimulatedBeacon) finalizedBlockHash(number uint64) *common.Hash {
|
||||||
|
var finalizedNumber uint64
|
||||||
|
if number%devEpochLength == 0 {
|
||||||
|
finalizedNumber = number
|
||||||
|
} else {
|
||||||
|
finalizedNumber = (number - 1) / devEpochLength * devEpochLength
|
||||||
|
}
|
||||||
|
|
||||||
|
if finalizedBlock := c.eth.BlockChain().GetBlockByNumber(finalizedNumber); finalizedBlock != nil {
|
||||||
|
fh := finalizedBlock.Hash()
|
||||||
|
return &fh
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// setCurrentState sets the current forkchoice state
|
||||||
|
func (c *SimulatedBeacon) setCurrentState(headHash, finalizedHash common.Hash) {
|
||||||
|
c.curForkchoiceState = engine.ForkchoiceStateV1{
|
||||||
|
HeadBlockHash: headHash,
|
||||||
|
SafeBlockHash: headHash,
|
||||||
|
FinalizedBlockHash: finalizedHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
|
func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
|
||||||
stack.RegisterAPIs([]rpc.API{
|
stack.RegisterAPIs([]rpc.API{
|
||||||
|
Loading…
Reference in New Issue
Block a user