From f740a26397b694de9a43e842ad7fdf7ad5d2dabd Mon Sep 17 00:00:00 2001 From: rjl493456442 Date: Mon, 26 Jul 2021 14:32:48 +0800 Subject: [PATCH] miner: add test --- miner/worker.go | 15 ++++--- miner/worker_test.go | 104 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 6 deletions(-) diff --git a/miner/worker.go b/miner/worker.go index efe3b6b895177..5cd351d7da9e1 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -110,7 +110,7 @@ func (env *environment) copy() *environment { if env.gasPool != nil { cpy.gasPool = &(*env.gasPool) } - // the content of txs and uncles are immutable, unnecessary + // The content of txs and uncles are immutable, unnecessary // to do the expensive deep copy for them. cpy.txs = make([]*types.Transaction, len(env.txs)) copy(cpy.txs, env.txs) @@ -150,7 +150,7 @@ type newWorkReq struct { timestamp int64 } -// getWorkReq represents a request for getting a unsealed block with provided parameters. +// getWorkReq represents a request for getting a new sealing work with provided parameters. type getWorkReq struct { params *generateParams err error @@ -500,7 +500,7 @@ func (w *worker) mainLoop() { defer w.chainHeadSub.Unsubscribe() defer w.chainSideSub.Unsubscribe() - cleanTicker := time.NewTicker(time.Minute) + cleanTicker := time.NewTicker(time.Second * 10) defer cleanTicker.Stop() for { @@ -509,12 +509,12 @@ func (w *worker) mainLoop() { w.commitWork(req.interrupt, req.noempty, req.timestamp) case req := <-w.getWorkCh: - unsealed, err := w.generateWork(req.params) + block, err := w.generateWork(req.params) if err != nil { req.err = err req.result <- nil } else { - req.result <- unsealed + req.result <- block } case ev := <-w.chainSideCh: @@ -721,7 +721,10 @@ func (w *worker) resultLoop() { // makeEnv creates a new environment for the sealing block. func (w *worker) makeEnv(parent *types.Block, header *types.Header) (*environment, error) { // Retrieve the parent state to execute on top and start a prefetcher for - // the miner to speed block sealing up a bit + // the miner to speed block sealing up a bit. Note since the sealing block + // can be created upon the arbitrary parent block, but the state of parent + // block may already be pruned, so the necessary state recovery is needed + // here in the future. TODO(rjl493456442). state, err := w.chain.StateAt(parent.Root()) if err != nil { return nil, err diff --git a/miner/worker_test.go b/miner/worker_test.go index 2bb6c9407bbec..00f46faa37c71 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -520,3 +520,107 @@ func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine co t.Error("interval reset timeout") } } + +func TestGetSealingWorkEthash(t *testing.T) { + testGetSealingWork(t, ethashChainConfig, ethash.NewFaker()) +} + +func TestGetSealingWorkClique(t *testing.T) { + testGetSealingWork(t, cliqueChainConfig, clique.New(cliqueChainConfig.Clique, rawdb.NewMemoryDatabase())) +} + +func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { + defer engine.Close() + + w, b := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0) + defer w.close() + + w.setExtra([]byte{0x01, 0x02}) + w.postSideBlock(core.ChainSideEvent{Block: b.uncleBlock}) + + w.skipSealHook = func(task *task) bool { + return true + } + w.fullTaskHook = func() { + time.Sleep(100 * time.Millisecond) + } + timestamp := uint64(time.Now().Unix()) + _, clique := engine.(*clique.Clique) + assertBlock := func(block *types.Block, number uint64) { + if block.Time() != timestamp { + t.Errorf("Invalid timestamp, want %d, get %d", timestamp, block.Time()) + } + if len(block.Uncles()) != 0 { + t.Error("Unexpected uncle block") + } + if !clique { + if len(block.Extra()) != 0 { + t.Error("Unexpected extra field") + } + if block.Coinbase() != w.coinbase { + t.Errorf("Invalid coinbase, want %x, get %x", w.coinbase, block.Coinbase()) + } + } + if block.MixDigest() != (common.Hash{}) { + t.Error("Unexpected mix digest") + } + if block.Nonce() != 0 { + t.Error("Unexpected block nonce") + } + if block.NumberU64() != number { + t.Errorf("Mismatched block number, want %d got %d", number, block.NumberU64()) + } + } + var cases = []struct { + parent common.Hash + expectNumber uint64 + expectErr bool + }{ + { + b.chain.Genesis().Hash(), + uint64(1), + false, + }, + { + b.chain.CurrentBlock().Hash(), + b.chain.CurrentBlock().NumberU64() + 1, + false, + }, + { + common.HexToHash("0xdeadbeef"), + 0, + true, + }, + } + + // This API should work even the automatic sealing is not enabled + for _, c := range cases { + block, err := w.getSealingBlock(c.parent, timestamp) + if c.expectErr { + if err == nil { + t.Error("Expect error but get nil") + } + } else { + if err != nil { + t.Errorf("Unexpected error %v", err) + } + assertBlock(block, c.expectNumber) + } + } + + // This API should work when the automatic sealing is enabled + w.start() + for _, c := range cases { + block, err := w.getSealingBlock(c.parent, timestamp) + if c.expectErr { + if err == nil { + t.Error("Expect error but get nil") + } + } else { + if err != nil { + t.Errorf("Unexpected error %v", err) + } + assertBlock(block, c.expectNumber) + } + } +}