style: extract common functionality to increase readability

This commit is contained in:
Robert Zaremba 2020-05-08 07:59:49 +02:00
parent 8b72a9d02d
commit 60a82f61ca

View file

@ -288,6 +288,29 @@ func (w *worker) close() {
close(w.exitCh) close(w.exitCh)
} }
// recalcRecommit recalculates the resubmitting interval upon feedback.
// @target is the dration vale (time.Duration as floating point) where we want to go.
func recalcRecommit(minRecommit, prev time.Duration, target float64, inc bool) time.Duration {
var (
prevF = float64(prev.Nanoseconds())
next float64
)
if inc {
next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target+intervalAdjustBias)
max := float64(maxRecommitInterval.Nanoseconds())
if next > max {
next = max
}
} else {
next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target-intervalAdjustBias)
min := float64(minRecommit.Nanoseconds())
if next < min {
next = min
}
}
return time.Duration(int64(next))
}
// newWorkLoop is a standalone goroutine to submit new mining work upon received events. // newWorkLoop is a standalone goroutine to submit new mining work upon received events.
func (w *worker) newWorkLoop(recommit time.Duration) { func (w *worker) newWorkLoop(recommit time.Duration) {
var ( var (
@ -310,27 +333,6 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
timer.Reset(recommit) timer.Reset(recommit)
atomic.StoreInt32(&w.newTxs, 0) atomic.StoreInt32(&w.newTxs, 0)
} }
// recalcRecommit recalculates the resubmitting interval upon feedback.
recalcRecommit := func(target float64, inc bool) {
var (
prev = float64(recommit.Nanoseconds())
next float64
)
if inc {
next = prev*(1-intervalAdjustRatio) + intervalAdjustRatio*(target+intervalAdjustBias)
// Recap if interval is larger than the maximum time interval
if next > float64(maxRecommitInterval.Nanoseconds()) {
next = float64(maxRecommitInterval.Nanoseconds())
}
} else {
next = prev*(1-intervalAdjustRatio) + intervalAdjustRatio*(target-intervalAdjustBias)
// Recap if interval is less than the user specified minimum
if next < float64(minRecommit.Nanoseconds()) {
next = float64(minRecommit.Nanoseconds())
}
}
recommit = time.Duration(int64(next))
}
// clearPending cleans the stale pending tasks. // clearPending cleans the stale pending tasks.
clearPending := func(number uint64) { clearPending := func(number uint64) {
w.pendingMu.Lock() w.pendingMu.Lock()
@ -383,11 +385,12 @@ func (w *worker) newWorkLoop(recommit time.Duration) {
// Adjust resubmit interval by feedback. // Adjust resubmit interval by feedback.
if adjust.inc { if adjust.inc {
before := recommit before := recommit
recalcRecommit(float64(recommit.Nanoseconds())/adjust.ratio, true) target := float64(recommit.Nanoseconds()) / adjust.ratio
recommit = recalcRecommit(minRecommit, recommit, target, true)
log.Trace("Increase miner recommit interval", "from", before, "to", recommit) log.Trace("Increase miner recommit interval", "from", before, "to", recommit)
} else { } else {
before := recommit before := recommit
recalcRecommit(float64(minRecommit.Nanoseconds()), false) recommit = recalcRecommit(minRecommit, recommit, float64(minRecommit.Nanoseconds()), false)
log.Trace("Decrease miner recommit interval", "from", before, "to", recommit) log.Trace("Decrease miner recommit interval", "from", before, "to", recommit)
} }
@ -535,7 +538,7 @@ func (w *worker) taskLoop() {
continue continue
} }
w.pendingMu.Lock() w.pendingMu.Lock()
w.pendingTasks[w.engine.SealHash(task.block.Header())] = task w.pendingTasks[sealHash] = task
w.pendingMu.Unlock() w.pendingMu.Unlock()
if err := w.engine.Seal(w.chain, task.block, w.resultCh, stopCh); err != nil { if err := w.engine.Seal(w.chain, task.block, w.resultCh, stopCh); err != nil {
@ -954,13 +957,9 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64)
// and commits new work if consensus engine is running. // and commits new work if consensus engine is running.
func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error { func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error {
// Deep copy receipts here to avoid interaction between different tasks. // Deep copy receipts here to avoid interaction between different tasks.
receipts := make([]*types.Receipt, len(w.current.receipts)) receipts := w.copyCurrentReceipts()
for i, l := range w.current.receipts {
receipts[i] = new(types.Receipt)
*receipts[i] = *l
}
s := w.current.state.Copy() s := w.current.state.Copy()
block, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts) block, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, receipts)
if err != nil { if err != nil {
return err return err
} }
@ -971,15 +970,10 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
select { select {
case w.taskCh <- &task{receipts: receipts, state: s, block: block, createdAt: time.Now()}: case w.taskCh <- &task{receipts: receipts, state: s, block: block, createdAt: time.Now()}:
w.unconfirmed.Shift(block.NumberU64() - 1) w.unconfirmed.Shift(block.NumberU64() - 1)
feesWei := new(big.Int)
for i, tx := range block.Transactions() {
feesWei.Add(feesWei, new(big.Int).Mul(new(big.Int).SetUint64(receipts[i].GasUsed), tx.GasPrice()))
}
feesEth := new(big.Float).Quo(new(big.Float).SetInt(feesWei), new(big.Float).SetInt(big.NewInt(params.Ether)))
log.Info("Commit new mining work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()), log.Info("Commit new mining work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()),
"uncles", len(uncles), "txs", w.current.tcount, "gas", block.GasUsed(), "fees", feesEth, "elapsed", common.PrettyDuration(time.Since(start))) "uncles", len(uncles), "txs", w.current.tcount,
"gas", block.GasUsed(), "fees", totalFees(block, receipts),
"elapsed", common.PrettyDuration(time.Since(start)))
case <-w.exitCh: case <-w.exitCh:
log.Info("Worker has exited") log.Info("Worker has exited")
@ -991,6 +985,17 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
return nil return nil
} }
// deep copy current receipts. This is should be used whene an asynchronus process can modify
// current context.
func (w *worker) copyCurrentReceipts() []*types.Receipt {
receipts := make([]*types.Receipt, len(w.current.receipts))
for i, l := range w.current.receipts {
cpy := *l
receipts[i] = &cpy
}
return receipts
}
// postSideBlock fires a side chain event, only use it for testing. // postSideBlock fires a side chain event, only use it for testing.
func (w *worker) postSideBlock(event core.ChainSideEvent) { func (w *worker) postSideBlock(event core.ChainSideEvent) {
select { select {
@ -998,3 +1003,12 @@ func (w *worker) postSideBlock(event core.ChainSideEvent) {
case <-w.exitCh: case <-w.exitCh:
} }
} }
// computes total consumed fees in ETH. Block transactions and receipts have to have the same order.
func totalFees(block *types.Block, receipts []*types.Receipt) *big.Float {
feesWei := new(big.Int)
for i, tx := range block.Transactions() {
feesWei.Add(feesWei, new(big.Int).Mul(new(big.Int).SetUint64(receipts[i].GasUsed), tx.GasPrice()))
}
return new(big.Float).Quo(new(big.Float).SetInt(feesWei), new(big.Float).SetInt(big.NewInt(params.Ether)))
}