diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 17bb13c98c..13430ad565 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -366,12 +366,12 @@ var ( } MinerRecommitIntervalFlag = cli.DurationFlag{ Name: "miner.recommit", - Usage: "Time interval to recreate the block being mined.", + Usage: "Time interval to recreate the block being mined", Value: eth.DefaultConfig.MinerRecommit, } MinerNoVerfiyFlag = cli.BoolFlag{ Name: "miner.noverify", - Usage: "Disable remote sealing verification.", + Usage: "Disable remote sealing verification", } // Account settings UnlockedAccountFlag = cli.StringFlag{ diff --git a/consensus/consensus.go b/consensus/consensus.go index 3fa0ae2bb1..12ede7ff46 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -87,7 +87,10 @@ type Engine interface { uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) // Seal generates a new sealing request for the given input block and pushes - // the result in the given channel. + // the result into the given channel. + // + // Note, the method returns immediately and will send the result async. More + // than one result may also be returned depending on the consensus algorothm. Seal(chain ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error // SealHash returns the hash of a block prior to it being sealed. diff --git a/consensus/ethash/sealer.go b/consensus/ethash/sealer.go index 42503e251b..06c98a7811 100644 --- a/consensus/ethash/sealer.go +++ b/consensus/ethash/sealer.go @@ -55,7 +55,7 @@ func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, resu select { case results <- block.WithSeal(header): default: - log.Warn("Sealing result is not read by miner", "sealhash", ethash.SealHash(block.Header())) + log.Warn("Sealing result is not read by miner", "mode", "fake", "sealhash", ethash.SealHash(block.Header())) } return nil } @@ -88,14 +88,14 @@ func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, resu ethash.workCh <- &sealTask{block: block, results: results} } var ( - pend sync.WaitGroup - localResults = make(chan *types.Block) + pend sync.WaitGroup + locals = make(chan *types.Block) ) for i := 0; i < threads; i++ { pend.Add(1) go func(id int, nonce uint64) { defer pend.Done() - ethash.mine(block, id, nonce, abort, localResults) + ethash.mine(block, id, nonce, abort, locals) }(i, uint64(ethash.rand.Int63())) } // Wait until sealing is terminated or a nonce is found @@ -105,19 +105,20 @@ func (ethash *Ethash) Seal(chain consensus.ChainReader, block *types.Block, resu case <-stop: // Outside abort, stop all miner threads close(abort) - case result = <-localResults: + case result = <-locals: // One of the threads found a block, abort all others select { case results <- result: default: - log.Warn("Sealing result is not read by miner", "sealhash", ethash.SealHash(block.Header())) + log.Warn("Sealing result is not read by miner", "mode", "local", "sealhash", ethash.SealHash(block.Header())) } close(abort) case <-ethash.update: // Thread count was changed on user request, restart close(abort) - pend.Wait() - ethash.Seal(chain, block, results, stop) + if err := ethash.Seal(chain, block, results, stop); err != nil { + log.Error("Failed to restart sealing after update", "err", err) + } } // Wait for all miners to terminate and return the block pend.Wait() @@ -287,12 +288,12 @@ func (ethash *Ethash) remote(notify []string, noverify bool) { log.Debug("Work submitted is acceptable", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash()) return true default: - log.Warn("Sealing result is not read by miner", "sealhash", sealhash) + log.Warn("Sealing result is not read by miner", "mode", "remote", "sealhash", sealhash) return false } } // The submitted block is too old to accept, drop it. - log.Debug("Work submitted is too old", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash()) + log.Warn("Work submitted is too old", "number", solution.NumberU64(), "sealhash", sealhash, "hash", solution.Hash()) return false } diff --git a/consensus/ethash/sealer_test.go b/consensus/ethash/sealer_test.go index 987ca5bfdc..31d18b67c7 100644 --- a/consensus/ethash/sealer_test.go +++ b/consensus/ethash/sealer_test.go @@ -190,7 +190,7 @@ func TestStaleSubmission(t *testing.T) { t.Errorf("case %d block number mismatch, want %d, get %d", id+1, c.headers[c.submitIndex].Number.Uint64(), res.Header().Number.Uint64()) } if res.Header().ParentHash != c.headers[c.submitIndex].ParentHash { - t.Errorf("case %d block parent hash mismatch, want %d, get %d", id+1, c.headers[c.submitIndex].ParentHash.Hex(), res.Header().ParentHash.Hex()) + t.Errorf("case %d block parent hash mismatch, want %s, get %s", id+1, c.headers[c.submitIndex].ParentHash.Hex(), res.Header().ParentHash.Hex()) } case <-time.NewTimer(time.Second).C: t.Errorf("case %d fetch ethash result timeout", id+1) diff --git a/miner/worker.go b/miner/worker.go index d32680e4c9..ca68da6e94 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -524,12 +524,15 @@ func (w *worker) resultLoop() { if w.chain.HasBlock(block.Hash(), block.NumberU64()) { continue } - sealhash := w.engine.SealHash(block.Header()) + var ( + sealhash = w.engine.SealHash(block.Header()) + hash = block.Hash() + ) w.pendingMu.RLock() task, exist := w.pendingTasks[sealhash] w.pendingMu.RUnlock() if !exist { - log.Error("Block found but no relative pending task", "number", block.Number(), "sealhash", sealhash, "hash", block.Hash()) + log.Error("Block found but no relative pending task", "number", block.Number(), "sealhash", sealhash, "hash", hash) continue } // Different block could share same sealhash, deep copy here to prevent write-write conflict. @@ -543,9 +546,9 @@ func (w *worker) resultLoop() { // Update the block hash in all logs since it is now available and not when the // receipt/log of individual transactions were created. for _, log := range receipt.Logs { - log.BlockHash = block.Hash() - logs = append(logs, log) + log.BlockHash = hash } + logs = append(logs, receipt.Logs...) } // Commit block and state to database. stat, err := w.chain.WriteBlockWithState(block, receipts, task.state) @@ -553,8 +556,12 @@ func (w *worker) resultLoop() { log.Error("Failed writing block to chain", "err", err) continue } + log.Info("Successfully sealed new block", "number", block.Number(), "sealhash", sealhash, "hash", hash, + "elapsed", common.PrettyDuration(time.Since(task.createdAt))) + // Broadcast the block and announce chain insertion event w.mux.Post(core.NewMinedBlockEvent{Block: block}) + var events []interface{} switch stat { case core.CanonStatTy: