github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/miner/worker.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:40</date>
    10  //</624450100676005888>
    11  
    12  
    13  package miner
    14  
    15  import (
    16  	"bytes"
    17  	"errors"
    18  	"math/big"
    19  	"sync"
    20  	"sync/atomic"
    21  	"time"
    22  
    23  	mapset "github.com/deckarep/golang-set"
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/consensus"
    26  	"github.com/ethereum/go-ethereum/consensus/misc"
    27  	"github.com/ethereum/go-ethereum/core"
    28  	"github.com/ethereum/go-ethereum/core/state"
    29  	"github.com/ethereum/go-ethereum/core/types"
    30  	"github.com/ethereum/go-ethereum/event"
    31  	"github.com/ethereum/go-ethereum/log"
    32  	"github.com/ethereum/go-ethereum/params"
    33  )
    34  
    35  const (
    36  //结果QueueSize为监听密封结果的通道大小。
    37  	resultQueueSize = 10
    38  
    39  //txchanSize是侦听newtxSevent的频道的大小。
    40  //该数字是根据Tx池的大小引用的。
    41  	txChanSize = 4096
    42  
    43  //ChainHeadChansize是侦听ChainHeadEvent的通道的大小。
    44  	chainHeadChanSize = 10
    45  
    46  //ChainsideChansize是侦听ChainsideEvent的通道的大小。
    47  	chainSideChanSize = 10
    48  
    49  //SubmitadjustChansize是重新提交间隔调整通道的大小。
    50  	resubmitAdjustChanSize = 10
    51  
    52  //MiningLogAtDepth是记录成功挖掘之前的确认数。
    53  	miningLogAtDepth = 7
    54  
    55  //MinRecommitInterval是重新创建挖掘块所用的最小时间间隔。
    56  //任何新到的交易。
    57  	minRecommitInterval = 1 * time.Second
    58  
    59  //MaxRecommitInterval是重新创建挖掘块所用的最大时间间隔
    60  //任何新到的交易。
    61  	maxRecommitInterval = 15 * time.Second
    62  
    63  //间隙调整是单个间隙调整对密封工作的影响。
    64  //重新提交间隔。
    65  	intervalAdjustRatio = 0.1
    66  
    67  //在新的重新提交间隔计算期间应用IntervalAdjustBias,有利于
    68  //增大上限或减小下限,以便可以达到上限。
    69  	intervalAdjustBias = 200 * 1000.0 * 1000.0
    70  
    71  //StaleThreshold是可接受的Stale块的最大深度。
    72  	staleThreshold = 7
    73  )
    74  
    75  //环境是工作人员的当前环境,保存所有当前状态信息。
    76  type environment struct {
    77  	signer types.Signer
    78  
    79  state     *state.StateDB //在此应用状态更改
    80  ancestors mapset.Set     //祖先集(用于检查叔叔父级有效性)
    81  family    mapset.Set     //家庭设置(用于检查叔叔的无效性)
    82  uncles    mapset.Set     //叔叔集
    83  tcount    int            //周期中的Tx计数
    84  gasPool   *core.GasPool  //用于包装交易的可用气体
    85  
    86  	header   *types.Header
    87  	txs      []*types.Transaction
    88  	receipts []*types.Receipt
    89  }
    90  
    91  //任务包含共识引擎密封和结果提交的所有信息。
    92  type task struct {
    93  	receipts  []*types.Receipt
    94  	state     *state.StateDB
    95  	block     *types.Block
    96  	createdAt time.Time
    97  }
    98  
    99  const (
   100  	commitInterruptNone int32 = iota
   101  	commitInterruptNewHead
   102  	commitInterruptResubmit
   103  )
   104  
   105  //newworkreq表示使用相关中断通知程序提交新密封工作的请求。
   106  type newWorkReq struct {
   107  	interrupt *int32
   108  	noempty   bool
   109  	timestamp int64
   110  }
   111  
   112  //IntervalAdjust表示重新提交的间隔调整。
   113  type intervalAdjust struct {
   114  	ratio float64
   115  	inc   bool
   116  }
   117  
   118  //工作人员是负责向共识引擎提交新工作的主要对象。
   119  //收集密封结果。
   120  type worker struct {
   121  	config *params.ChainConfig
   122  	engine consensus.Engine
   123  	eth    Backend
   124  	chain  *core.BlockChain
   125  
   126  	gasFloor uint64
   127  	gasCeil  uint64
   128  
   129  //订阅
   130  	mux          *event.TypeMux
   131  	txsCh        chan core.NewTxsEvent
   132  	txsSub       event.Subscription
   133  	chainHeadCh  chan core.ChainHeadEvent
   134  	chainHeadSub event.Subscription
   135  	chainSideCh  chan core.ChainSideEvent
   136  	chainSideSub event.Subscription
   137  
   138  //渠道
   139  	newWorkCh          chan *newWorkReq
   140  	taskCh             chan *task
   141  	resultCh           chan *types.Block
   142  	startCh            chan struct{}
   143  	exitCh             chan struct{}
   144  	resubmitIntervalCh chan time.Duration
   145  	resubmitAdjustCh   chan *intervalAdjust
   146  
   147  current      *environment                 //当前运行周期的环境。
   148  localUncles  map[common.Hash]*types.Block //局部生成的一组边块,作为可能的叔叔块。
   149  remoteUncles map[common.Hash]*types.Block //一组侧块作为可能的叔叔块。
   150  unconfirmed  *unconfirmedBlocks           //一组本地挖掘的块,等待规范性确认。
   151  
   152  mu       sync.RWMutex //用于保护coinbase和额外字段的锁
   153  	coinbase common.Address
   154  	extra    []byte
   155  
   156  	pendingMu    sync.RWMutex
   157  	pendingTasks map[common.Hash]*task
   158  
   159  snapshotMu    sync.RWMutex //用于保护块快照和状态快照的锁
   160  	snapshotBlock *types.Block
   161  	snapshotState *state.StateDB
   162  
   163  //原子状态计数器
   164  running int32 //共识引擎是否运行的指示器。
   165  newTxs  int32 //自上次密封工作提交以来的新到达交易记录计数。
   166  
   167  //外部功能
   168  isLocalBlock func(block *types.Block) bool //用于确定指定块是否由本地矿工挖掘的函数。
   169  
   170  //测试钩
   171  newTaskHook  func(*task)                        //方法在收到新的密封任务时调用。
   172  skipSealHook func(*task) bool                   //方法来决定是否跳过密封。
   173  fullTaskHook func()                             //方法在执行完全密封任务之前调用。
   174  resubmitHook func(time.Duration, time.Duration) //更新重新提交间隔时调用的方法。
   175  }
   176  
   177  func newWorker(config *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, recommit time.Duration, gasFloor, gasCeil uint64, isLocalBlock func(*types.Block) bool) *worker {
   178  	worker := &worker{
   179  		config:             config,
   180  		engine:             engine,
   181  		eth:                eth,
   182  		mux:                mux,
   183  		chain:              eth.BlockChain(),
   184  		gasFloor:           gasFloor,
   185  		gasCeil:            gasCeil,
   186  		isLocalBlock:       isLocalBlock,
   187  		localUncles:        make(map[common.Hash]*types.Block),
   188  		remoteUncles:       make(map[common.Hash]*types.Block),
   189  		unconfirmed:        newUnconfirmedBlocks(eth.BlockChain(), miningLogAtDepth),
   190  		pendingTasks:       make(map[common.Hash]*task),
   191  		txsCh:              make(chan core.NewTxsEvent, txChanSize),
   192  		chainHeadCh:        make(chan core.ChainHeadEvent, chainHeadChanSize),
   193  		chainSideCh:        make(chan core.ChainSideEvent, chainSideChanSize),
   194  		newWorkCh:          make(chan *newWorkReq),
   195  		taskCh:             make(chan *task),
   196  		resultCh:           make(chan *types.Block, resultQueueSize),
   197  		exitCh:             make(chan struct{}),
   198  		startCh:            make(chan struct{}, 1),
   199  		resubmitIntervalCh: make(chan time.Duration),
   200  		resubmitAdjustCh:   make(chan *intervalAdjust, resubmitAdjustChanSize),
   201  	}
   202  //订阅Tx池的NewTxSevent
   203  	worker.txsSub = eth.TxPool().SubscribeNewTxsEvent(worker.txsCh)
   204  //为区块链订阅事件
   205  	worker.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(worker.chainHeadCh)
   206  	worker.chainSideSub = eth.BlockChain().SubscribeChainSideEvent(worker.chainSideCh)
   207  
   208  //如果用户指定的重新提交间隔太短,则清除重新提交间隔。
   209  	if recommit < minRecommitInterval {
   210  		log.Warn("Sanitizing miner recommit interval", "provided", recommit, "updated", minRecommitInterval)
   211  		recommit = minRecommitInterval
   212  	}
   213  
   214  	go worker.mainLoop()
   215  	go worker.newWorkLoop(recommit)
   216  	go worker.resultLoop()
   217  	go worker.taskLoop()
   218  
   219  //提交第一个工作以初始化挂起状态。
   220  	worker.startCh <- struct{}{}
   221  
   222  	return worker
   223  }
   224  
   225  //setetherbase设置用于初始化块coinbase字段的etherbase。
   226  func (w *worker) setEtherbase(addr common.Address) {
   227  	w.mu.Lock()
   228  	defer w.mu.Unlock()
   229  	w.coinbase = addr
   230  }
   231  
   232  //setextra设置用于初始化块额外字段的内容。
   233  func (w *worker) setExtra(extra []byte) {
   234  	w.mu.Lock()
   235  	defer w.mu.Unlock()
   236  	w.extra = extra
   237  }
   238  
   239  //setrecommittinterval更新矿工密封工作重新投入的时间间隔。
   240  func (w *worker) setRecommitInterval(interval time.Duration) {
   241  	w.resubmitIntervalCh <- interval
   242  }
   243  
   244  //Pending返回Pending状态和相应的块。
   245  func (w *worker) pending() (*types.Block, *state.StateDB) {
   246  //返回快照以避免对当前mutex的争用
   247  	w.snapshotMu.RLock()
   248  	defer w.snapshotMu.RUnlock()
   249  	if w.snapshotState == nil {
   250  		return nil, nil
   251  	}
   252  	return w.snapshotBlock, w.snapshotState.Copy()
   253  }
   254  
   255  //PendingBlock返回PendingBlock。
   256  func (w *worker) pendingBlock() *types.Block {
   257  //返回快照以避免对当前mutex的争用
   258  	w.snapshotMu.RLock()
   259  	defer w.snapshotMu.RUnlock()
   260  	return w.snapshotBlock
   261  }
   262  
   263  //Start将运行状态设置为1并触发新工作提交。
   264  func (w *worker) start() {
   265  	atomic.StoreInt32(&w.running, 1)
   266  	w.startCh <- struct{}{}
   267  }
   268  
   269  //stop将运行状态设置为0。
   270  func (w *worker) stop() {
   271  	atomic.StoreInt32(&w.running, 0)
   272  }
   273  
   274  //is running返回一个指示工作者是否正在运行的指示器。
   275  func (w *worker) isRunning() bool {
   276  	return atomic.LoadInt32(&w.running) == 1
   277  }
   278  
   279  //CLOSE终止工作线程维护的所有后台线程。
   280  //注意工人不支持多次关闭。
   281  func (w *worker) close() {
   282  	close(w.exitCh)
   283  }
   284  
   285  //newworkoop是一个独立的goroutine,用于在收到事件时提交新的挖掘工作。
   286  func (w *worker) newWorkLoop(recommit time.Duration) {
   287  	var (
   288  		interrupt   *int32
   289  minRecommit = recommit //用户指定的最小重新提交间隔。
   290  timestamp   int64      //每轮挖掘的时间戳。
   291  	)
   292  
   293  	timer := time.NewTimer(0)
   294  <-timer.C //放弃初始勾号
   295  
   296  //commit使用给定的信号中止正在执行的事务,并重新提交一个新的事务。
   297  	commit := func(noempty bool, s int32) {
   298  		if interrupt != nil {
   299  			atomic.StoreInt32(interrupt, s)
   300  		}
   301  		interrupt = new(int32)
   302  		w.newWorkCh <- &newWorkReq{interrupt: interrupt, noempty: noempty, timestamp: timestamp}
   303  		timer.Reset(recommit)
   304  		atomic.StoreInt32(&w.newTxs, 0)
   305  	}
   306  //重新计算提交根据反馈重新计算重新提交间隔。
   307  	recalcRecommit := func(target float64, inc bool) {
   308  		var (
   309  			prev = float64(recommit.Nanoseconds())
   310  			next float64
   311  		)
   312  		if inc {
   313  			next = prev*(1-intervalAdjustRatio) + intervalAdjustRatio*(target+intervalAdjustBias)
   314  //回顾间隔是否大于最大时间间隔
   315  			if next > float64(maxRecommitInterval.Nanoseconds()) {
   316  				next = float64(maxRecommitInterval.Nanoseconds())
   317  			}
   318  		} else {
   319  			next = prev*(1-intervalAdjustRatio) + intervalAdjustRatio*(target-intervalAdjustBias)
   320  //如果间隔小于用户指定的最小值,则重述
   321  			if next < float64(minRecommit.Nanoseconds()) {
   322  				next = float64(minRecommit.Nanoseconds())
   323  			}
   324  		}
   325  		recommit = time.Duration(int64(next))
   326  	}
   327  //ClearPending清除过时的挂起任务。
   328  	clearPending := func(number uint64) {
   329  		w.pendingMu.Lock()
   330  		for h, t := range w.pendingTasks {
   331  			if t.block.NumberU64()+staleThreshold <= number {
   332  				delete(w.pendingTasks, h)
   333  			}
   334  		}
   335  		w.pendingMu.Unlock()
   336  	}
   337  
   338  	for {
   339  		select {
   340  		case <-w.startCh:
   341  			clearPending(w.chain.CurrentBlock().NumberU64())
   342  			timestamp = time.Now().Unix()
   343  			commit(false, commitInterruptNewHead)
   344  
   345  		case head := <-w.chainHeadCh:
   346  			clearPending(head.Block.NumberU64())
   347  			timestamp = time.Now().Unix()
   348  			commit(false, commitInterruptNewHead)
   349  
   350  		case <-timer.C:
   351  //如果正在运行挖掘,请定期重新提交新的工作周期以拉入
   352  //高价交易。对挂起的块禁用此开销。
   353  			if w.isRunning() && (w.config.Clique == nil || w.config.Clique.Period > 0) {
   354  //如果没有新交易到达,则短路。
   355  				if atomic.LoadInt32(&w.newTxs) == 0 {
   356  					timer.Reset(recommit)
   357  					continue
   358  				}
   359  				commit(true, commitInterruptResubmit)
   360  			}
   361  
   362  		case interval := <-w.resubmitIntervalCh:
   363  //按用户明确调整重新提交间隔。
   364  			if interval < minRecommitInterval {
   365  				log.Warn("Sanitizing miner recommit interval", "provided", interval, "updated", minRecommitInterval)
   366  				interval = minRecommitInterval
   367  			}
   368  			log.Info("Miner recommit interval update", "from", minRecommit, "to", interval)
   369  			minRecommit, recommit = interval, interval
   370  
   371  			if w.resubmitHook != nil {
   372  				w.resubmitHook(minRecommit, recommit)
   373  			}
   374  
   375  		case adjust := <-w.resubmitAdjustCh:
   376  //通过反馈调整重新提交间隔。
   377  			if adjust.inc {
   378  				before := recommit
   379  				recalcRecommit(float64(recommit.Nanoseconds())/adjust.ratio, true)
   380  				log.Trace("Increase miner recommit interval", "from", before, "to", recommit)
   381  			} else {
   382  				before := recommit
   383  				recalcRecommit(float64(minRecommit.Nanoseconds()), false)
   384  				log.Trace("Decrease miner recommit interval", "from", before, "to", recommit)
   385  			}
   386  
   387  			if w.resubmitHook != nil {
   388  				w.resubmitHook(minRecommit, recommit)
   389  			}
   390  
   391  		case <-w.exitCh:
   392  			return
   393  		}
   394  	}
   395  }
   396  
   397  //mainLoop是一个独立的goroutine,用于根据接收到的事件重新生成密封任务。
   398  func (w *worker) mainLoop() {
   399  	defer w.txsSub.Unsubscribe()
   400  	defer w.chainHeadSub.Unsubscribe()
   401  	defer w.chainSideSub.Unsubscribe()
   402  
   403  	for {
   404  		select {
   405  		case req := <-w.newWorkCh:
   406  			w.commitNewWork(req.interrupt, req.noempty, req.timestamp)
   407  
   408  		case ev := <-w.chainSideCh:
   409  //重复侧块短路
   410  			if _, exist := w.localUncles[ev.Block.Hash()]; exist {
   411  				continue
   412  			}
   413  			if _, exist := w.remoteUncles[ev.Block.Hash()]; exist {
   414  				continue
   415  			}
   416  //根据作者,将侧块添加到可能的叔叔块集。
   417  			if w.isLocalBlock != nil && w.isLocalBlock(ev.Block) {
   418  				w.localUncles[ev.Block.Hash()] = ev.Block
   419  			} else {
   420  				w.remoteUncles[ev.Block.Hash()] = ev.Block
   421  			}
   422  //如果我们的采矿区块少于2个叔叔区块,
   423  //添加新的叔叔块(如果有效)并重新生成挖掘块。
   424  			if w.isRunning() && w.current != nil && w.current.uncles.Cardinality() < 2 {
   425  				start := time.Now()
   426  				if err := w.commitUncle(w.current, ev.Block.Header()); err == nil {
   427  					var uncles []*types.Header
   428  					w.current.uncles.Each(func(item interface{}) bool {
   429  						hash, ok := item.(common.Hash)
   430  						if !ok {
   431  							return false
   432  						}
   433  						uncle, exist := w.localUncles[hash]
   434  						if !exist {
   435  							uncle, exist = w.remoteUncles[hash]
   436  						}
   437  						if !exist {
   438  							return false
   439  						}
   440  						uncles = append(uncles, uncle.Header())
   441  						return false
   442  					})
   443  					w.commit(uncles, nil, true, start)
   444  				}
   445  			}
   446  
   447  		case ev := <-w.txsCh:
   448  //如果不挖掘,将事务应用于挂起状态。
   449  //
   450  //注意:收到的所有交易可能与交易不连续。
   451  //已包含在当前挖掘块中。这些交易将
   452  //自动消除。
   453  			if !w.isRunning() && w.current != nil {
   454  				w.mu.RLock()
   455  				coinbase := w.coinbase
   456  				w.mu.RUnlock()
   457  
   458  				txs := make(map[common.Address]types.Transactions)
   459  				for _, tx := range ev.Txs {
   460  					acc, _ := types.Sender(w.current.signer, tx)
   461  					txs[acc] = append(txs[acc], tx)
   462  				}
   463  				txset := types.NewTransactionsByPriceAndNonce(w.current.signer, txs)
   464  				w.commitTransactions(txset, coinbase, nil)
   465  				w.updateSnapshot()
   466  			} else {
   467  //如果我们正在挖掘,但没有处理任何事务,请唤醒新事务
   468  				if w.config.Clique != nil && w.config.Clique.Period == 0 {
   469  					w.commitNewWork(nil, false, time.Now().Unix())
   470  				}
   471  			}
   472  			atomic.AddInt32(&w.newTxs, int32(len(ev.Txs)))
   473  
   474  //系统停止
   475  		case <-w.exitCh:
   476  			return
   477  		case <-w.txsSub.Err():
   478  			return
   479  		case <-w.chainHeadSub.Err():
   480  			return
   481  		case <-w.chainSideSub.Err():
   482  			return
   483  		}
   484  	}
   485  }
   486  
   487  //taskloop是一个独立的goroutine,用于从生成器获取密封任务,并且
   488  //把他们推到共识引擎。
   489  func (w *worker) taskLoop() {
   490  	var (
   491  		stopCh chan struct{}
   492  		prev   common.Hash
   493  	)
   494  
   495  //中断中止飞行中的密封任务。
   496  	interrupt := func() {
   497  		if stopCh != nil {
   498  			close(stopCh)
   499  			stopCh = nil
   500  		}
   501  	}
   502  	for {
   503  		select {
   504  		case task := <-w.taskCh:
   505  			if w.newTaskHook != nil {
   506  				w.newTaskHook(task)
   507  			}
   508  //因重新提交而拒绝重复密封工作。
   509  			sealHash := w.engine.SealHash(task.block.Header())
   510  			if sealHash == prev {
   511  				continue
   512  			}
   513  //中断之前的密封操作
   514  			interrupt()
   515  			stopCh, prev = make(chan struct{}), sealHash
   516  
   517  			if w.skipSealHook != nil && w.skipSealHook(task) {
   518  				continue
   519  			}
   520  			w.pendingMu.Lock()
   521  			w.pendingTasks[w.engine.SealHash(task.block.Header())] = task
   522  			w.pendingMu.Unlock()
   523  
   524  			if err := w.engine.Seal(w.chain, task.block, w.resultCh, stopCh); err != nil {
   525  				log.Warn("Block sealing failed", "err", err)
   526  			}
   527  		case <-w.exitCh:
   528  			interrupt()
   529  			return
   530  		}
   531  	}
   532  }
   533  
   534  //resultLoop是一个独立的goroutine,用于处理密封结果提交
   535  //并将相关数据刷新到数据库。
   536  func (w *worker) resultLoop() {
   537  	for {
   538  		select {
   539  		case block := <-w.resultCh:
   540  //收到空结果时短路。
   541  			if block == nil {
   542  				continue
   543  			}
   544  //由于重新提交而收到重复结果时短路。
   545  			if w.chain.HasBlock(block.Hash(), block.NumberU64()) {
   546  				continue
   547  			}
   548  			var (
   549  				sealhash = w.engine.SealHash(block.Header())
   550  				hash     = block.Hash()
   551  			)
   552  			w.pendingMu.RLock()
   553  			task, exist := w.pendingTasks[sealhash]
   554  			w.pendingMu.RUnlock()
   555  			if !exist {
   556  				log.Error("Block found but no relative pending task", "number", block.Number(), "sealhash", sealhash, "hash", hash)
   557  				continue
   558  			}
   559  //不同的块可以共享相同的sealhash,在这里进行深度复制以防止写写冲突。
   560  			var (
   561  				receipts = make([]*types.Receipt, len(task.receipts))
   562  				logs     []*types.Log
   563  			)
   564  			for i, receipt := range task.receipts {
   565  				receipts[i] = new(types.Receipt)
   566  				*receipts[i] = *receipt
   567  //更新所有日志中的块哈希,因为它现在可用,而不是
   568  //已创建单个交易的收据/日志。
   569  				for _, log := range receipt.Logs {
   570  					log.BlockHash = hash
   571  				}
   572  				logs = append(logs, receipt.Logs...)
   573  			}
   574  //将块和状态提交到数据库。
   575  			stat, err := w.chain.WriteBlockWithState(block, receipts, task.state)
   576  			if err != nil {
   577  				log.Error("Failed writing block to chain", "err", err)
   578  				continue
   579  			}
   580  			log.Info("Successfully sealed new block", "number", block.Number(), "sealhash", sealhash, "hash", hash,
   581  				"elapsed", common.PrettyDuration(time.Since(task.createdAt)))
   582  
   583  //广播块并宣布链插入事件
   584  			w.mux.Post(core.NewMinedBlockEvent{Block: block})
   585  
   586  			var events []interface{}
   587  			switch stat {
   588  			case core.CanonStatTy:
   589  				events = append(events, core.ChainEvent{Block: block, Hash: block.Hash(), Logs: logs})
   590  				events = append(events, core.ChainHeadEvent{Block: block})
   591  			case core.SideStatTy:
   592  				events = append(events, core.ChainSideEvent{Block: block})
   593  			}
   594  			w.chain.PostChainEvents(events, logs)
   595  
   596  //将块插入一组挂起的结果循环以进行确认
   597  			w.unconfirmed.Insert(block.NumberU64(), block.Hash())
   598  
   599  		case <-w.exitCh:
   600  			return
   601  		}
   602  	}
   603  }
   604  
   605  //makecurrent为当前循环创建新环境。
   606  func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error {
   607  	state, err := w.chain.StateAt(parent.Root())
   608  	if err != nil {
   609  		return err
   610  	}
   611  	env := &environment{
   612  		signer:    types.NewEIP155Signer(w.config.ChainID),
   613  		state:     state,
   614  		ancestors: mapset.NewSet(),
   615  		family:    mapset.NewSet(),
   616  		uncles:    mapset.NewSet(),
   617  		header:    header,
   618  	}
   619  
   620  //处理08时,祖先包含07(快速块)
   621  	for _, ancestor := range w.chain.GetBlocksFromHash(parent.Hash(), 7) {
   622  		for _, uncle := range ancestor.Uncles() {
   623  			env.family.Add(uncle.Hash())
   624  		}
   625  		env.family.Add(ancestor.Hash())
   626  		env.ancestors.Add(ancestor.Hash())
   627  	}
   628  
   629  //跟踪返回错误的事务,以便删除它们
   630  	env.tcount = 0
   631  	w.current = env
   632  	return nil
   633  }
   634  
   635  //commituncle将给定的块添加到叔叔块集,如果添加失败则返回错误。
   636  func (w *worker) commitUncle(env *environment, uncle *types.Header) error {
   637  	hash := uncle.Hash()
   638  	if env.uncles.Contains(hash) {
   639  		return errors.New("uncle not unique")
   640  	}
   641  	if env.header.ParentHash == uncle.ParentHash {
   642  		return errors.New("uncle is sibling")
   643  	}
   644  	if !env.ancestors.Contains(uncle.ParentHash) {
   645  		return errors.New("uncle's parent unknown")
   646  	}
   647  	if env.family.Contains(hash) {
   648  		return errors.New("uncle already included")
   649  	}
   650  	env.uncles.Add(uncle.Hash())
   651  	return nil
   652  }
   653  
   654  //更新快照更新挂起的快照块和状态。
   655  //注意:此函数假定当前变量是线程安全的。
   656  func (w *worker) updateSnapshot() {
   657  	w.snapshotMu.Lock()
   658  	defer w.snapshotMu.Unlock()
   659  
   660  	var uncles []*types.Header
   661  	w.current.uncles.Each(func(item interface{}) bool {
   662  		hash, ok := item.(common.Hash)
   663  		if !ok {
   664  			return false
   665  		}
   666  		uncle, exist := w.localUncles[hash]
   667  		if !exist {
   668  			uncle, exist = w.remoteUncles[hash]
   669  		}
   670  		if !exist {
   671  			return false
   672  		}
   673  		uncles = append(uncles, uncle.Header())
   674  		return false
   675  	})
   676  
   677  	w.snapshotBlock = types.NewBlock(
   678  		w.current.header,
   679  		w.current.txs,
   680  		uncles,
   681  		w.current.receipts,
   682  	)
   683  
   684  	w.snapshotState = w.current.state.Copy()
   685  }
   686  
   687  func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address) ([]*types.Log, error) {
   688  	snap := w.current.state.Snapshot()
   689  
   690  	receipt, _, err := core.ApplyTransaction(w.config, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig())
   691  	if err != nil {
   692  		w.current.state.RevertToSnapshot(snap)
   693  		return nil, err
   694  	}
   695  	w.current.txs = append(w.current.txs, tx)
   696  	w.current.receipts = append(w.current.receipts, receipt)
   697  
   698  	return receipt.Logs, nil
   699  }
   700  
   701  func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coinbase common.Address, interrupt *int32) bool {
   702  //电流为零时短路
   703  	if w.current == nil {
   704  		return true
   705  	}
   706  
   707  	if w.current.gasPool == nil {
   708  		w.current.gasPool = new(core.GasPool).AddGas(w.current.header.GasLimit)
   709  	}
   710  
   711  	var coalescedLogs []*types.Log
   712  
   713  	for {
   714  //在以下三种情况下,我们将中断事务的执行。
   715  //(1)新的头块事件到达,中断信号为1
   716  //(2)工人启动或重启,中断信号为1
   717  //(3)工人用任何新到达的事务重新创建挖掘块,中断信号为2。
   718  //前两种情况下,半成品将被丢弃。
   719  //对于第三种情况,半成品将提交给共识引擎。
   720  		if interrupt != nil && atomic.LoadInt32(interrupt) != commitInterruptNone {
   721  //由于提交太频繁,通知重新提交循环以增加重新提交间隔。
   722  			if atomic.LoadInt32(interrupt) == commitInterruptResubmit {
   723  				ratio := float64(w.current.header.GasLimit-w.current.gasPool.Gas()) / float64(w.current.header.GasLimit)
   724  				if ratio < 0.1 {
   725  					ratio = 0.1
   726  				}
   727  				w.resubmitAdjustCh <- &intervalAdjust{
   728  					ratio: ratio,
   729  					inc:   true,
   730  				}
   731  			}
   732  			return atomic.LoadInt32(interrupt) == commitInterruptNewHead
   733  		}
   734  //如果我们没有足够的汽油进行进一步的交易,那么我们就完成了
   735  		if w.current.gasPool.Gas() < params.TxGas {
   736  			log.Trace("Not enough gas for further transactions", "have", w.current.gasPool, "want", params.TxGas)
   737  			break
   738  		}
   739  //检索下一个事务,完成后中止
   740  		tx := txs.Peek()
   741  		if tx == nil {
   742  			break
   743  		}
   744  //此处可以忽略错误。已检查错误
   745  //在事务接受期间是事务池。
   746  //
   747  //我们使用EIP155签名者,不管当前的高频。
   748  		from, _ := types.Sender(w.current.signer, tx)
   749  //检查Tx是否受重播保护。如果我们不在EIP155高频
   750  //阶段,开始忽略发送者,直到我们这样做。
   751  		if tx.Protected() && !w.config.IsEIP155(w.current.header.Number) {
   752  			log.Trace("Ignoring reply protected transaction", "hash", tx.Hash(), "eip155", w.config.EIP155Block)
   753  
   754  			txs.Pop()
   755  			continue
   756  		}
   757  //开始执行事务
   758  		w.current.state.Prepare(tx.Hash(), common.Hash{}, w.current.tcount)
   759  
   760  		logs, err := w.commitTransaction(tx, coinbase)
   761  		switch err {
   762  		case core.ErrGasLimitReached:
   763  //从账户中弹出当前的天然气外交易,而不在下一个账户中移动。
   764  			log.Trace("Gas limit exceeded for current block", "sender", from)
   765  			txs.Pop()
   766  
   767  		case core.ErrNonceTooLow:
   768  //事务池和矿工之间的新头通知数据竞赛,shift
   769  			log.Trace("Skipping transaction with low nonce", "sender", from, "nonce", tx.Nonce())
   770  			txs.Shift()
   771  
   772  		case core.ErrNonceTooHigh:
   773  //交易池和矿工之间的REORG通知数据竞赛,跳过帐户=
   774  			log.Trace("Skipping account with hight nonce", "sender", from, "nonce", tx.Nonce())
   775  			txs.Pop()
   776  
   777  		case nil:
   778  //一切正常,收集日志并从同一帐户转入下一个事务
   779  			coalescedLogs = append(coalescedLogs, logs...)
   780  			w.current.tcount++
   781  			txs.Shift()
   782  
   783  		default:
   784  //奇怪的错误,丢弃事务并将下一个事务处理到行中(注意,
   785  //nonce-too-high子句将阻止我们无效执行)。
   786  			log.Debug("Transaction failed, account skipped", "hash", tx.Hash(), "err", err)
   787  			txs.Shift()
   788  		}
   789  	}
   790  
   791  	if !w.isRunning() && len(coalescedLogs) > 0 {
   792  //我们在采矿时不会推悬垂的日志。原因是
   793  //当我们进行挖掘时,工人将每3秒重新生成一个挖掘块。
   794  //为了避免推送重复的挂起日志,我们禁用挂起日志推送。
   795  
   796  //复制,状态缓存日志,这些日志从挂起升级到挖掘。
   797  //当块由当地矿工开采时,通过填充块散列进行记录。这个罐头
   798  //如果在处理PendingLogSevent之前日志已“升级”,则会导致竞争条件。
   799  		cpy := make([]*types.Log, len(coalescedLogs))
   800  		for i, l := range coalescedLogs {
   801  			cpy[i] = new(types.Log)
   802  			*cpy[i] = *l
   803  		}
   804  		go w.mux.Post(core.PendingLogsEvent{Logs: cpy})
   805  	}
   806  //如果当前间隔较大,通知重新提交循环以减少重新提交间隔
   807  //而不是用户指定的。
   808  	if interrupt != nil {
   809  		w.resubmitAdjustCh <- &intervalAdjust{inc: false}
   810  	}
   811  	return false
   812  }
   813  
   814  //CommitnewWork基于父块生成几个新的密封任务。
   815  func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) {
   816  	w.mu.RLock()
   817  	defer w.mu.RUnlock()
   818  
   819  	tstart := time.Now()
   820  	parent := w.chain.CurrentBlock()
   821  
   822  	if parent.Time().Cmp(new(big.Int).SetInt64(timestamp)) >= 0 {
   823  		timestamp = parent.Time().Int64() + 1
   824  	}
   825  //这将确保我们今后不会走得太远。
   826  	if now := time.Now().Unix(); timestamp > now+1 {
   827  		wait := time.Duration(timestamp-now) * time.Second
   828  		log.Info("Mining too far in the future", "wait", common.PrettyDuration(wait))
   829  		time.Sleep(wait)
   830  	}
   831  
   832  	num := parent.Number()
   833  	header := &types.Header{
   834  		ParentHash: parent.Hash(),
   835  		Number:     num.Add(num, common.Big1),
   836  		GasLimit:   core.CalcGasLimit(parent, w.gasFloor, w.gasCeil),
   837  		Extra:      w.extra,
   838  		Time:       big.NewInt(timestamp),
   839  	}
   840  //只有在我们的共识引擎运行时才设置coinbase(避免虚假的块奖励)
   841  	if w.isRunning() {
   842  		if w.coinbase == (common.Address{}) {
   843  			log.Error("Refusing to mine without etherbase")
   844  			return
   845  		}
   846  		header.Coinbase = w.coinbase
   847  	}
   848  	if err := w.engine.Prepare(w.chain, header); err != nil {
   849  		log.Error("Failed to prepare header for mining", "err", err)
   850  		return
   851  	}
   852  //如果我们关心DAO硬分叉,请检查是否覆盖额外的数据
   853  	if daoBlock := w.config.DAOForkBlock; daoBlock != nil {
   854  //检查块是否在fork额外覆盖范围内
   855  		limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
   856  		if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 {
   857  //根据我们是支持还是反对叉子,以不同的方式超越
   858  			if w.config.DAOForkSupport {
   859  				header.Extra = common.CopyBytes(params.DAOForkBlockExtra)
   860  			} else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
   861  header.Extra = []byte{} //如果Miner反对,不要让它使用保留的额外数据
   862  			}
   863  		}
   864  	}
   865  //如果在一个奇怪的状态下开始挖掘,可能会发生这种情况。
   866  	err := w.makeCurrent(parent, header)
   867  	if err != nil {
   868  		log.Error("Failed to create mining context", "err", err)
   869  		return
   870  	}
   871  //创建当前工作任务并检查所需的任何分叉转换
   872  	env := w.current
   873  	if w.config.DAOForkSupport && w.config.DAOForkBlock != nil && w.config.DAOForkBlock.Cmp(header.Number) == 0 {
   874  		misc.ApplyDAOHardFork(env.state)
   875  	}
   876  //累积当前块的叔叔
   877  	uncles := make([]*types.Header, 0, 2)
   878  	commitUncles := func(blocks map[common.Hash]*types.Block) {
   879  //先清理陈旧的叔叔街区
   880  		for hash, uncle := range blocks {
   881  			if uncle.NumberU64()+staleThreshold <= header.Number.Uint64() {
   882  				delete(blocks, hash)
   883  			}
   884  		}
   885  		for hash, uncle := range blocks {
   886  			if len(uncles) == 2 {
   887  				break
   888  			}
   889  			if err := w.commitUncle(env, uncle.Header()); err != nil {
   890  				log.Trace("Possible uncle rejected", "hash", hash, "reason", err)
   891  			} else {
   892  				log.Debug("Committing new uncle to block", "hash", hash)
   893  				uncles = append(uncles, uncle.Header())
   894  			}
   895  		}
   896  	}
   897  //更喜欢本地生成的叔叔
   898  	commitUncles(w.localUncles)
   899  	commitUncles(w.remoteUncles)
   900  
   901  	if !noempty {
   902  //基于临时复制状态创建一个空块,在不等待块的情况下提前密封
   903  //执行完成。
   904  		w.commit(uncles, nil, false, tstart)
   905  	}
   906  
   907  //用所有可用的挂起事务填充块。
   908  	pending, err := w.eth.TxPool().Pending()
   909  	if err != nil {
   910  		log.Error("Failed to fetch pending transactions", "err", err)
   911  		return
   912  	}
   913  //如果没有可用的挂起事务,则短路
   914  	if len(pending) == 0 {
   915  		w.updateSnapshot()
   916  		return
   917  	}
   918  //将挂起的事务拆分为本地和远程
   919  	localTxs, remoteTxs := make(map[common.Address]types.Transactions), pending
   920  	for _, account := range w.eth.TxPool().Locals() {
   921  		if txs := remoteTxs[account]; len(txs) > 0 {
   922  			delete(remoteTxs, account)
   923  			localTxs[account] = txs
   924  		}
   925  	}
   926  	if len(localTxs) > 0 {
   927  		txs := types.NewTransactionsByPriceAndNonce(w.current.signer, localTxs)
   928  		if w.commitTransactions(txs, w.coinbase, interrupt) {
   929  			return
   930  		}
   931  	}
   932  	if len(remoteTxs) > 0 {
   933  		txs := types.NewTransactionsByPriceAndNonce(w.current.signer, remoteTxs)
   934  		if w.commitTransactions(txs, w.coinbase, interrupt) {
   935  			return
   936  		}
   937  	}
   938  	w.commit(uncles, w.fullTaskHook, true, tstart)
   939  }
   940  
   941  //commit运行任何事务后状态修改,组装最终块
   942  //如果共识引擎正在运行,则提交新的工作。
   943  func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error {
   944  //在此深度复制收据以避免不同任务之间的交互。
   945  	receipts := make([]*types.Receipt, len(w.current.receipts))
   946  	for i, l := range w.current.receipts {
   947  		receipts[i] = new(types.Receipt)
   948  		*receipts[i] = *l
   949  	}
   950  	s := w.current.state.Copy()
   951  	block, err := w.engine.Finalize(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts)
   952  	if err != nil {
   953  		return err
   954  	}
   955  	if w.isRunning() {
   956  		if interval != nil {
   957  			interval()
   958  		}
   959  		select {
   960  		case w.taskCh <- &task{receipts: receipts, state: s, block: block, createdAt: time.Now()}:
   961  			w.unconfirmed.Shift(block.NumberU64() - 1)
   962  
   963  			feesWei := new(big.Int)
   964  			for i, tx := range block.Transactions() {
   965  				feesWei.Add(feesWei, new(big.Int).Mul(new(big.Int).SetUint64(receipts[i].GasUsed), tx.GasPrice()))
   966  			}
   967  			feesEth := new(big.Float).Quo(new(big.Float).SetInt(feesWei), new(big.Float).SetInt(big.NewInt(params.Ether)))
   968  
   969  			log.Info("Commit new mining work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()),
   970  				"uncles", len(uncles), "txs", w.current.tcount, "gas", block.GasUsed(), "fees", feesEth, "elapsed", common.PrettyDuration(time.Since(start)))
   971  
   972  		case <-w.exitCh:
   973  			log.Info("Worker has exited")
   974  		}
   975  	}
   976  	if update {
   977  		w.updateSnapshot()
   978  	}
   979  	return nil
   980  }
   981