diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go index c71add93bc99..e4e2ca774607 100644 --- a/eth/catalyst/simulated_beacon.go +++ b/eth/catalyst/simulated_beacon.go @@ -80,6 +80,17 @@ func (w *withdrawalQueue) subscribe(ch chan<- newWithdrawalsEvent) event.Subscri return w.subs.Track(sub) } +// errTxPoolTerminated is returned when the txpool is already terminated when +// trying to seal a block. +type errTxPoolTerminated struct { + error +} + +// Error returns the message from the wrapped error. +func (t *errTxPoolTerminated) Error() string { + return fmt.Errorf("failed to sync txpool: %w", t.error).Error() +} + // SimulatedBeacon drives an Ethereum instance as if it were a real beacon // client. It can run in period mode where it mines a new block every period // (seconds) or on every transaction via Commit, Fork and AdjustTime. @@ -181,7 +192,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u // behavior, the pool will be explicitly blocked on its reset before // continuing to the block production below. if err := c.eth.APIBackend.TxPool().Sync(); err != nil { - return fmt.Errorf("failed to sync txpool: %w", err) + return &errTxPoolTerminated{err} } version := payloadVersion(c.eth.BlockChain().Config(), timestamp) @@ -302,11 +313,18 @@ func (c *SimulatedBeacon) setCurrentState(headHash, finalizedHash common.Hash) { // Commit seals a block on demand. func (c *SimulatedBeacon) Commit() common.Hash { + hash, _ := c.commit() + return hash +} + +// commit attempts to seal a block on demand, but may return an error. +func (c *SimulatedBeacon) commit() (common.Hash, error) { withdrawals := c.withdrawals.pop(10) if err := c.sealBlock(withdrawals, uint64(time.Now().Unix())); err != nil { log.Warn("Error performing sealing work", "err", err) + return common.Hash{}, err } - return c.eth.BlockChain().CurrentBlock().Hash() + return c.eth.BlockChain().CurrentBlock().Hash(), nil } // Rollback un-sends previously added transactions. diff --git a/eth/catalyst/simulated_beacon_api.go b/eth/catalyst/simulated_beacon_api.go index 668780531501..34047a964c80 100644 --- a/eth/catalyst/simulated_beacon_api.go +++ b/eth/catalyst/simulated_beacon_api.go @@ -18,6 +18,7 @@ package catalyst import ( "context" + "errors" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -70,7 +71,12 @@ func (a *simulatedBeaconAPI) loop() { if executable, _ := a.sim.eth.TxPool().Stats(); executable == 0 { break } - a.sim.Commit() + // Avoids spinlooping if the txPool is alredy terminated. + if _, err := a.sim.commit(); err != nil { + if errors.Is(err, &errTxPoolTerminated{}) { + break + } + } } } }()