mirror of
https://github.com/status-im/op-geth.git
synced 2025-02-12 06:46:25 +00:00
Merge pull request #93 from ethereum-optimism/fix-pending-block
miner,eth: latest block as pending block on rollup
This commit is contained in:
commit
bdab05ca78
@ -156,6 +156,7 @@ var (
|
||||
utils.RollupHistoricalRPCFlag,
|
||||
utils.RollupHistoricalRPCTimeoutFlag,
|
||||
utils.RollupDisableTxPoolGossipFlag,
|
||||
utils.RollupComputePendingBlock,
|
||||
configFileFlag,
|
||||
}, utils.NetworkFlags, utils.DatabasePathFlags)
|
||||
|
||||
|
@ -941,6 +941,11 @@ var (
|
||||
Usage: "Disable transaction pool gossip.",
|
||||
Category: flags.RollupCategory,
|
||||
}
|
||||
RollupComputePendingBlock = &cli.BoolFlag{
|
||||
Name: "rollup.computependingblock",
|
||||
Usage: "By default the pending block equals the latest block to save resources and not leak txs from the tx-pool, this flag enables computing of the pending block from the tx-pool instead.",
|
||||
Category: flags.RollupCategory,
|
||||
}
|
||||
|
||||
// Metrics flags
|
||||
MetricsEnabledFlag = &cli.BoolFlag{
|
||||
@ -1696,6 +1701,9 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
|
||||
if ctx.IsSet(MinerNewPayloadTimeout.Name) {
|
||||
cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name)
|
||||
}
|
||||
if ctx.IsSet(RollupComputePendingBlock.Name) {
|
||||
cfg.RollupComputePendingBlock = ctx.Bool(RollupComputePendingBlock.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||
|
@ -265,6 +265,9 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
|
||||
// both the pending block as well as the pending state from
|
||||
// the miner and operate on those
|
||||
_, stateDb := api.eth.miner.Pending()
|
||||
if stateDb == nil {
|
||||
return state.Dump{}, errors.New("no pending state")
|
||||
}
|
||||
return stateDb.RawDump(opts), nil
|
||||
}
|
||||
var header *types.Header
|
||||
@ -350,6 +353,9 @@ func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hex
|
||||
// both the pending block as well as the pending state from
|
||||
// the miner and operate on those
|
||||
_, stateDb = api.eth.miner.Pending()
|
||||
if stateDb == nil {
|
||||
return state.IteratorDump{}, errors.New("no pending state")
|
||||
}
|
||||
} else {
|
||||
var header *types.Header
|
||||
if number == rpc.LatestBlockNumber {
|
||||
|
@ -199,7 +199,11 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B
|
||||
// Pending state is only known by the miner
|
||||
if number == rpc.PendingBlockNumber {
|
||||
block, state := b.eth.miner.Pending()
|
||||
return state, block.Header(), nil
|
||||
if block != nil {
|
||||
return state, block.Header(), nil
|
||||
} else {
|
||||
number = rpc.LatestBlockNumber
|
||||
}
|
||||
}
|
||||
// Otherwise resolve the block number and return its state
|
||||
header, err := b.HeaderByNumber(ctx, number)
|
||||
|
@ -774,7 +774,7 @@ func (s *BlockChainAPI) GetHeaderByNumber(ctx context.Context, number rpc.BlockN
|
||||
header, err := s.b.HeaderByNumber(ctx, number)
|
||||
if header != nil && err == nil {
|
||||
response := s.rpcMarshalHeader(ctx, header)
|
||||
if number == rpc.PendingBlockNumber {
|
||||
if number == rpc.PendingBlockNumber && s.b.ChainConfig().Optimism == nil { // don't remove info if optimism
|
||||
// Pending header need to nil out a few fields
|
||||
for _, field := range []string{"hash", "nonce", "miner"} {
|
||||
response[field] = nil
|
||||
@ -803,7 +803,7 @@ func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNu
|
||||
block, err := s.b.BlockByNumber(ctx, number)
|
||||
if block != nil && err == nil {
|
||||
response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
|
||||
if err == nil && number == rpc.PendingBlockNumber {
|
||||
if err == nil && number == rpc.PendingBlockNumber && s.b.ChainConfig().Optimism == nil { // don't remove info if optimism
|
||||
// Pending blocks need to nil out a few fields
|
||||
for _, field := range []string{"hash", "nonce", "miner"} {
|
||||
response[field] = nil
|
||||
|
@ -62,6 +62,8 @@ type Config struct {
|
||||
Noverify bool // Disable remote mining solution verification(only useful in ethash).
|
||||
|
||||
NewPayloadTimeout time.Duration // The maximum time allowance for creating a new payload
|
||||
|
||||
RollupComputePendingBlock bool // Compute the pending block from tx-pool, instead of copying the latest-block
|
||||
}
|
||||
|
||||
// DefaultConfig contains default settings for miner.
|
||||
|
@ -384,6 +384,9 @@ func (w *worker) enablePreseal() {
|
||||
|
||||
// pending returns the pending state and corresponding block.
|
||||
func (w *worker) pending() (*types.Block, *state.StateDB) {
|
||||
if w.chainConfig.Optimism != nil && !w.config.RollupComputePendingBlock {
|
||||
return nil, nil // when not computing the pending block, there is never a pending state
|
||||
}
|
||||
// return a snapshot to avoid contention on currentMu mutex
|
||||
w.snapshotMu.RLock()
|
||||
defer w.snapshotMu.RUnlock()
|
||||
@ -395,6 +398,12 @@ func (w *worker) pending() (*types.Block, *state.StateDB) {
|
||||
|
||||
// pendingBlock returns pending block.
|
||||
func (w *worker) pendingBlock() *types.Block {
|
||||
if w.chainConfig.Optimism != nil && !w.config.RollupComputePendingBlock {
|
||||
// For compatibility when not computing a pending block, we serve the latest block as "pending"
|
||||
headHeader := w.eth.BlockChain().CurrentHeader()
|
||||
headBlock := w.eth.BlockChain().GetBlock(headHeader.Hash(), headHeader.Number.Uint64())
|
||||
return headBlock
|
||||
}
|
||||
// return a snapshot to avoid contention on currentMu mutex
|
||||
w.snapshotMu.RLock()
|
||||
defer w.snapshotMu.RUnlock()
|
||||
@ -403,6 +412,9 @@ func (w *worker) pendingBlock() *types.Block {
|
||||
|
||||
// pendingBlockAndReceipts returns pending block and corresponding receipts.
|
||||
func (w *worker) pendingBlockAndReceipts() (*types.Block, types.Receipts) {
|
||||
if w.chainConfig.Optimism != nil && !w.config.RollupComputePendingBlock {
|
||||
return nil, nil // when not computing the pending block, there are no pending receipts, and thus no pending logs
|
||||
}
|
||||
// return a snapshot to avoid contention on currentMu mutex
|
||||
w.snapshotMu.RLock()
|
||||
defer w.snapshotMu.RUnlock()
|
||||
@ -458,6 +470,19 @@ func recalcRecommit(minRecommit, prev time.Duration, target float64, inc bool) t
|
||||
// newWorkLoop is a standalone goroutine to submit new sealing work upon received events.
|
||||
func (w *worker) newWorkLoop(recommit time.Duration) {
|
||||
defer w.wg.Done()
|
||||
if w.chainConfig.Optimism != nil && !w.config.RollupComputePendingBlock {
|
||||
for { // do not update the pending-block, instead drain work without doing it, to keep producers from blocking.
|
||||
select {
|
||||
case <-w.startCh:
|
||||
case <-w.chainHeadCh:
|
||||
case <-w.resubmitIntervalCh:
|
||||
case <-w.resubmitAdjustCh:
|
||||
case <-w.exitCh:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
interrupt *atomic.Int32
|
||||
minRecommit = recommit // minimal resubmit interval specified by user.
|
||||
@ -620,6 +645,9 @@ func (w *worker) mainLoop() {
|
||||
}
|
||||
|
||||
case ev := <-w.txsCh:
|
||||
if w.chainConfig.Optimism != nil && !w.config.RollupComputePendingBlock {
|
||||
continue // don't update the pending-block snapshot if we are not computing the pending block
|
||||
}
|
||||
// Apply transactions to the pending state if we're not sealing
|
||||
//
|
||||
// Note all transactions received may not be continuous with transactions
|
||||
|
Loading…
x
Reference in New Issue
Block a user