Skip to content

Commit 7875af9

Browse files
committed
Treat Clique block interval as a timeout
1 parent 054bbd2 commit 7875af9

File tree

3 files changed

+43
-455
lines changed

3 files changed

+43
-455
lines changed

consensus/clique/clique.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header
328328
if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
329329
return consensus.ErrUnknownAncestor
330330
}
331-
if parent.Time+c.config.Period > header.Time {
331+
if parent.Time > header.Time {
332332
return errInvalidTimestamp
333333
}
334334
// Verify that the gasUsed is <= gasLimit
@@ -554,10 +554,6 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
554554
if parent == nil {
555555
return consensus.ErrUnknownAncestor
556556
}
557-
header.Time = parent.Time + c.config.Period
558-
if header.Time < uint64(time.Now().Unix()) {
559-
header.Time = uint64(time.Now().Unix())
560-
}
561557
return nil
562558
}
563559

miner/worker.go

+42-149
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ type environment struct {
126126
traceEnv *tracing.TraceEnv // env for tracing
127127
accRows *types.RowConsumption // accumulated row consumption for a block
128128
nextL1MsgIndex uint64 // next L1 queue index to be processed
129+
start time.Time // time we started building this block
129130
}
130131

131132
// task contains all information for consensus engine sealing and result submitting.
@@ -424,15 +425,10 @@ func recalcRecommit(minRecommit, prev time.Duration, target float64, inc bool) t
424425
func (w *worker) newWorkLoop(recommit time.Duration) {
425426
defer w.wg.Done()
426427
var (
427-
interrupt *int32
428-
minRecommit = recommit // minimal resubmit interval specified by user.
429-
timestamp int64 // timestamp for each round of mining.
428+
interrupt *int32
429+
timestamp int64 // timestamp for each round of mining.
430430
)
431431

432-
timer := time.NewTimer(0)
433-
defer timer.Stop()
434-
<-timer.C // discard the initial tick
435-
436432
// commit aborts in-flight transaction execution with given signal and resubmits a new one.
437433
commit := func(noempty bool, s int32) {
438434
if interrupt != nil {
@@ -444,7 +440,6 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
444440
case <-w.exitCh:
445441
return
446442
}
447-
timer.Reset(recommit)
448443
atomic.StoreInt32(&w.newTxs, 0)
449444
atomic.StoreInt32(&w.newL1Msgs, 0)
450445
}
@@ -465,54 +460,10 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
465460
clearPending(w.chain.CurrentBlock().NumberU64())
466461
timestamp = time.Now().Unix()
467462
commit(false, commitInterruptNewHead)
468-
469463
case head := <-w.chainHeadCh:
470464
clearPending(head.Block.NumberU64())
471465
timestamp = time.Now().Unix()
472466
commit(true, commitInterruptNewHead)
473-
474-
case <-timer.C:
475-
// If mining is running resubmit a new work cycle periodically to pull in
476-
// higher priced transactions. Disable this overhead for pending blocks.
477-
if w.isRunning() && (w.chainConfig.Clique == nil || w.chainConfig.Clique.Period > 0) {
478-
// Short circuit if no new transaction arrives.
479-
if atomic.LoadInt32(&w.newTxs) == 0 && atomic.LoadInt32(&w.newL1Msgs) == 0 {
480-
timer.Reset(recommit)
481-
continue
482-
}
483-
commit(true, commitInterruptResubmit)
484-
}
485-
486-
case interval := <-w.resubmitIntervalCh:
487-
// Adjust resubmit interval explicitly by user.
488-
if interval < minRecommitInterval {
489-
log.Warn("Sanitizing miner recommit interval", "provided", interval, "updated", minRecommitInterval)
490-
interval = minRecommitInterval
491-
}
492-
log.Info("Miner recommit interval update", "from", minRecommit, "to", interval)
493-
minRecommit, recommit = interval, interval
494-
495-
if w.resubmitHook != nil {
496-
w.resubmitHook(minRecommit, recommit)
497-
}
498-
499-
case adjust := <-w.resubmitAdjustCh:
500-
// Adjust resubmit interval by feedback.
501-
if adjust.inc {
502-
before := recommit
503-
target := float64(recommit.Nanoseconds()) / adjust.ratio
504-
recommit = recalcRecommit(minRecommit, recommit, target, true)
505-
log.Trace("Increase miner recommit interval", "from", before, "to", recommit)
506-
} else {
507-
before := recommit
508-
recommit = recalcRecommit(minRecommit, recommit, float64(minRecommit.Nanoseconds()), false)
509-
log.Trace("Decrease miner recommit interval", "from", before, "to", recommit)
510-
}
511-
512-
if w.resubmitHook != nil {
513-
w.resubmitHook(minRecommit, recommit)
514-
}
515-
516467
case <-w.exitCh:
517468
return
518469
}
@@ -532,58 +483,29 @@ func (w *worker) mainLoop() {
532483
}
533484
}()
534485

486+
sealTimer := time.NewTimer(0)
487+
defer sealTimer.Stop()
488+
535489
for {
536490
select {
537491
case req := <-w.newWorkCh:
538492
w.commitNewWork(req.interrupt, req.noempty, req.timestamp)
539-
// new block created.
540-
541-
case ev := <-w.chainSideCh:
542-
// Short circuit for duplicate side blocks
543-
if _, exist := w.localUncles[ev.Block.Hash()]; exist {
544-
continue
493+
if w.chainConfig.Clique != nil {
494+
sealTimer.Reset(time.Duration(w.chainConfig.Clique.Period) * time.Second)
545495
}
546-
if _, exist := w.remoteUncles[ev.Block.Hash()]; exist {
547-
continue
548-
}
549-
// Add side block to possible uncle block set depending on the author.
550-
if w.isLocalBlock != nil && w.isLocalBlock(ev.Block) {
551-
w.localUncles[ev.Block.Hash()] = ev.Block
496+
case <-sealTimer.C:
497+
if w.current != nil && w.current.tcount != 0 {
498+
w.commit(nil, w.fullTaskHook, true)
552499
} else {
553-
w.remoteUncles[ev.Block.Hash()] = ev.Block
500+
sealTimer.Reset(time.Second)
554501
}
555-
// If our mining block contains less than 2 uncle blocks,
556-
// add the new uncle block if valid and regenerate a mining block.
557-
if w.isRunning() && w.current != nil && w.current.uncles.Cardinality() < 2 {
558-
start := time.Now()
559-
if err := w.commitUncle(w.current, ev.Block.Header()); err == nil {
560-
var uncles []*types.Header
561-
w.current.uncles.Each(func(item interface{}) bool {
562-
hash, ok := item.(common.Hash)
563-
if !ok {
564-
return false
565-
}
566-
uncle, exist := w.localUncles[hash]
567-
if !exist {
568-
uncle, exist = w.remoteUncles[hash]
569-
}
570-
if !exist {
571-
return false
572-
}
573-
uncles = append(uncles, uncle.Header())
574-
return false
575-
})
576-
w.commit(uncles, nil, true, start)
577-
}
578-
}
579-
580502
case ev := <-w.txsCh:
581-
// Apply transactions to the pending state if we're not mining.
503+
// Apply transactions to the pending state
582504
//
583505
// Note all transactions received may not be continuous with transactions
584506
// already included in the current mining block. These transactions will
585507
// be automatically eliminated.
586-
if !w.isRunning() && w.current != nil {
508+
if w.current != nil {
587509
// If block is already full, abort
588510
if gp := w.current.gasPool; gp != nil && gp.Gas() < params.TxGas {
589511
continue
@@ -599,10 +521,11 @@ func (w *worker) mainLoop() {
599521
}
600522
txset := types.NewTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
601523
tcount := w.current.tcount
602-
w.commitTransactions(txset, coinbase, nil)
603-
// Only update the snapshot if any new transactons were added
604-
// to the pending block
605-
if tcount != w.current.tcount {
524+
if seal := w.commitTransactions(txset, coinbase, nil); seal {
525+
w.commit(nil, w.fullTaskHook, true)
526+
} else if tcount != w.current.tcount {
527+
// Only update the snapshot if any new transactons were added
528+
// to the pending block
606529
w.updateSnapshot()
607530
}
608531
} else {
@@ -799,7 +722,7 @@ func (w *worker) resultLoop() {
799722
}
800723

801724
// makeCurrent creates a new environment for the current cycle.
802-
func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
725+
func (w *worker) makeCurrent(parent *types.Block, header *types.Header, start time.Time) error {
803726
// Retrieve the parent state to execute on top and start a prefetcher for
804727
// the miner to speed block sealing up a bit
805728
state, err := w.chain.StateAt(parent.Root())
@@ -829,6 +752,7 @@ func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
829752
header: header,
830753
traceEnv: traceEnv,
831754
accRows: nil,
755+
start: start,
832756
}
833757
// when 08 is processed ancestors contain 07 (quick block)
834758
for _, ancestor := range w.chain.GetBlocksFromHash(parent.Hash(), 7) {
@@ -995,7 +919,7 @@ func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Addres
995919
return receipt.Logs, traces, nil
996920
}
997921

998-
func (w *worker) commitTransactions(txs types.OrderedTransactionSet, coinbase common.Address, interrupt *int32) (bool, bool) {
922+
func (w *worker) commitTransactions(txs types.OrderedTransactionSet, coinbase common.Address, interrupt *int32) bool {
999923
defer func(t0 time.Time) {
1000924
l2CommitTxsTimer.Update(time.Since(t0))
1001925
}(time.Now())
@@ -1004,7 +928,7 @@ func (w *worker) commitTransactions(txs types.OrderedTransactionSet, coinbase co
1004928

1005929
// Short circuit if current is nil
1006930
if w.current == nil {
1007-
return true, circuitCapacityReached
931+
return false
1008932
}
1009933

1010934
gasLimit := w.current.header.GasLimit
@@ -1023,18 +947,7 @@ loop:
1023947
// For the first two cases, the semi-finished work will be discarded.
1024948
// For the third case, the semi-finished work will be submitted to the consensus engine.
1025949
if interrupt != nil && atomic.LoadInt32(interrupt) != commitInterruptNone {
1026-
// Notify resubmit loop to increase resubmitting interval due to too frequent commits.
1027-
if atomic.LoadInt32(interrupt) == commitInterruptResubmit {
1028-
ratio := float64(gasLimit-w.current.gasPool.Gas()) / float64(gasLimit)
1029-
if ratio < 0.1 {
1030-
ratio = 0.1
1031-
}
1032-
w.resubmitAdjustCh <- &intervalAdjust{
1033-
ratio: ratio,
1034-
inc: true,
1035-
}
1036-
}
1037-
return atomic.LoadInt32(interrupt) == commitInterruptNewHead, circuitCapacityReached
950+
return false
1038951
}
1039952
// If we don't have enough gas for any further transactions then we're done
1040953
if w.current.gasPool.Gas() < params.TxGas {
@@ -1274,12 +1187,7 @@ loop:
12741187
}
12751188
w.pendingLogsFeed.Send(cpy)
12761189
}
1277-
// Notify resubmit loop to decrease resubmitting interval if current interval is larger
1278-
// than the user-specified one.
1279-
if interrupt != nil {
1280-
w.resubmitAdjustCh <- &intervalAdjust{inc: false}
1281-
}
1282-
return false, circuitCapacityReached
1190+
return circuitCapacityReached
12831191
}
12841192

12851193
func (w *worker) checkCurrentTxNumWithCCC(expected int) {
@@ -1312,9 +1220,6 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
13121220
w.circuitCapacityChecker.Reset()
13131221
log.Trace("Worker reset ccc", "id", w.circuitCapacityChecker.ID)
13141222

1315-
if parent.Time() >= uint64(timestamp) {
1316-
timestamp = int64(parent.Time() + 1)
1317-
}
13181223
num := parent.Number()
13191224
header := &types.Header{
13201225
ParentHash: parent.Hash(),
@@ -1359,7 +1264,7 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
13591264
}
13601265
}
13611266
// Could potentially happen if starting to mine in an odd state.
1362-
err := w.makeCurrent(parent, header)
1267+
err := w.makeCurrent(parent, header, tstart)
13631268
if err != nil {
13641269
log.Error("Failed to create mining context", "err", err)
13651270
return
@@ -1394,11 +1299,6 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
13941299
commitUncles(w.localUncles)
13951300
commitUncles(w.remoteUncles)
13961301

1397-
// Create an empty block based on temporary copied state for
1398-
// sealing in advance without waiting block execution finished.
1399-
if !noempty && atomic.LoadUint32(&w.noempty) == 0 {
1400-
w.commit(uncles, nil, false, tstart)
1401-
}
14021302
// fetch l1Txs
14031303
var l1Messages []types.L1MessageTx
14041304
if w.chainConfig.Scroll.ShouldIncludeL1Messages() {
@@ -1423,60 +1323,52 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
14231323
localTxs[account] = txs
14241324
}
14251325
}
1426-
var skipCommit, circuitCapacityReached bool
1326+
14271327
if w.chainConfig.Scroll.ShouldIncludeL1Messages() && len(l1Messages) > 0 {
14281328
log.Trace("Processing L1 messages for inclusion", "count", len(l1Messages))
14291329
txs, err := types.NewL1MessagesByQueueIndex(l1Messages)
14301330
if err != nil {
14311331
log.Error("Failed to create L1 message set", "l1Messages", l1Messages, "err", err)
14321332
return
14331333
}
1434-
skipCommit, circuitCapacityReached = w.commitTransactions(txs, w.coinbase, interrupt)
1435-
if skipCommit {
1334+
1335+
if seal := w.commitTransactions(txs, w.coinbase, interrupt); seal {
1336+
w.commit(uncles, w.fullTaskHook, true)
14361337
return
14371338
}
14381339
}
14391340
if w.prioritizedTx != nil && w.current.header.Number.Uint64() > w.prioritizedTx.blockNumber {
14401341
w.prioritizedTx = nil
14411342
}
1442-
if !circuitCapacityReached && w.prioritizedTx != nil && w.current.header.Number.Uint64() == w.prioritizedTx.blockNumber {
1343+
if w.prioritizedTx != nil && w.current.header.Number.Uint64() == w.prioritizedTx.blockNumber {
14431344
tx := w.prioritizedTx.tx
14441345
from, _ := types.Sender(w.current.signer, tx) // error already checked before
14451346
txList := map[common.Address]types.Transactions{from: []*types.Transaction{tx}}
14461347
txs := types.NewTransactionsByPriceAndNonce(w.current.signer, txList, header.BaseFee)
1447-
skipCommit, circuitCapacityReached = w.commitTransactions(txs, w.coinbase, interrupt)
1448-
if skipCommit {
1348+
if seal := w.commitTransactions(txs, w.coinbase, interrupt); seal {
1349+
w.commit(uncles, w.fullTaskHook, true)
14491350
return
14501351
}
14511352
}
1452-
if len(localTxs) > 0 && !circuitCapacityReached {
1353+
if len(localTxs) > 0 {
14531354
txs := types.NewTransactionsByPriceAndNonce(w.current.signer, localTxs, header.BaseFee)
1454-
skipCommit, circuitCapacityReached = w.commitTransactions(txs, w.coinbase, interrupt)
1455-
if skipCommit {
1355+
if seal := w.commitTransactions(txs, w.coinbase, interrupt); seal {
1356+
w.commit(uncles, w.fullTaskHook, true)
14561357
return
14571358
}
14581359
}
1459-
if len(remoteTxs) > 0 && !circuitCapacityReached {
1360+
if len(remoteTxs) > 0 {
14601361
txs := types.NewTransactionsByPriceAndNonce(w.current.signer, remoteTxs, header.BaseFee)
1461-
// don't need to get `circuitCapacityReached` here because we don't have further `commitTransactions`
1462-
// after this one, and if we assign it won't take effect (`ineffassign`)
1463-
skipCommit, _ = w.commitTransactions(txs, w.coinbase, interrupt)
1464-
if skipCommit {
1362+
if seal := w.commitTransactions(txs, w.coinbase, interrupt); seal {
1363+
w.commit(uncles, w.fullTaskHook, true)
14651364
return
14661365
}
14671366
}
1468-
1469-
// do not produce empty blocks
1470-
if w.current.tcount == 0 {
1471-
return
1472-
}
1473-
1474-
w.commit(uncles, w.fullTaskHook, true, tstart)
14751367
}
14761368

14771369
// commit runs any post-transaction state modifications, assembles the final block
14781370
// and commits new work if consensus engine is running.
1479-
func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error {
1371+
func (w *worker) commit(uncles []*types.Header, interval func(), update bool) error {
14801372
defer func(t0 time.Time) {
14811373
l2CommitTimer.Update(time.Since(t0))
14821374
}(time.Now())
@@ -1536,7 +1428,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
15361428
log.Info("Commit new mining work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()),
15371429
"uncles", len(uncles), "txs", w.current.tcount,
15381430
"gas", block.GasUsed(), "fees", totalFees(block, receipts),
1539-
"elapsed", common.PrettyDuration(time.Since(start)))
1431+
"elapsed", common.PrettyDuration(time.Since(w.current.start)))
15401432

15411433
case <-w.exitCh:
15421434
log.Info("Worker has exited")
@@ -1545,6 +1437,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
15451437
if update {
15461438
w.updateSnapshot()
15471439
}
1440+
w.current = nil
15481441
return nil
15491442
}
15501443

0 commit comments

Comments
 (0)