github.com/phillinzzz/newBsc@v1.1.6/miner/worker.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package miner 18 19 import ( 20 "bytes" 21 "errors" 22 "math/big" 23 "sync" 24 "sync/atomic" 25 "time" 26 27 mapset "github.com/deckarep/golang-set" 28 "github.com/phillinzzz/newBsc/common" 29 "github.com/phillinzzz/newBsc/consensus" 30 "github.com/phillinzzz/newBsc/consensus/misc" 31 "github.com/phillinzzz/newBsc/consensus/parlia" 32 "github.com/phillinzzz/newBsc/core" 33 "github.com/phillinzzz/newBsc/core/state" 34 "github.com/phillinzzz/newBsc/core/systemcontracts" 35 "github.com/phillinzzz/newBsc/core/types" 36 "github.com/phillinzzz/newBsc/event" 37 "github.com/phillinzzz/newBsc/log" 38 "github.com/phillinzzz/newBsc/metrics" 39 "github.com/phillinzzz/newBsc/params" 40 "github.com/phillinzzz/newBsc/trie" 41 ) 42 43 const ( 44 // resultQueueSize is the size of channel listening to sealing result. 45 resultQueueSize = 10 46 47 // txChanSize is the size of channel listening to NewTxsEvent. 48 // The number is referenced from the size of tx pool. 49 txChanSize = 4096 50 51 // chainHeadChanSize is the size of channel listening to ChainHeadEvent. 52 chainHeadChanSize = 10 53 54 // chainSideChanSize is the size of channel listening to ChainSideEvent. 55 chainSideChanSize = 10 56 57 // resubmitAdjustChanSize is the size of resubmitting interval adjustment channel. 58 resubmitAdjustChanSize = 10 59 60 // miningLogAtDepth is the number of confirmations before logging successful mining. 61 miningLogAtDepth = 11 62 63 // minRecommitInterval is the minimal time interval to recreate the mining block with 64 // any newly arrived transactions. 65 minRecommitInterval = 1 * time.Second 66 67 // maxRecommitInterval is the maximum time interval to recreate the mining block with 68 // any newly arrived transactions. 69 maxRecommitInterval = 15 * time.Second 70 71 // intervalAdjustRatio is the impact a single interval adjustment has on sealing work 72 // resubmitting interval. 73 intervalAdjustRatio = 0.1 74 75 // intervalAdjustBias is applied during the new resubmit interval calculation in favor of 76 // increasing upper limit or decreasing lower limit so that the limit can be reachable. 77 intervalAdjustBias = 200 * 1000.0 * 1000.0 78 79 // staleThreshold is the maximum depth of the acceptable stale block. 80 staleThreshold = 11 81 ) 82 83 var ( 84 commitTxsTimer = metrics.NewRegisteredTimer("worker/committxs", nil) 85 ) 86 87 // environment is the worker's current environment and holds all of the current state information. 88 type environment struct { 89 signer types.Signer 90 91 state *state.StateDB // apply state changes here 92 ancestors mapset.Set // ancestor set (used for checking uncle parent validity) 93 family mapset.Set // family set (used for checking uncle invalidity) 94 uncles mapset.Set // uncle set 95 tcount int // tx count in cycle 96 gasPool *core.GasPool // available gas used to pack transactions 97 98 header *types.Header 99 txs []*types.Transaction 100 receipts []*types.Receipt 101 } 102 103 // task contains all information for consensus engine sealing and result submitting. 104 type task struct { 105 receipts []*types.Receipt 106 state *state.StateDB 107 block *types.Block 108 createdAt time.Time 109 } 110 111 const ( 112 commitInterruptNone int32 = iota 113 commitInterruptNewHead 114 commitInterruptResubmit 115 ) 116 117 // newWorkReq represents a request for new sealing work submitting with relative interrupt notifier. 118 type newWorkReq struct { 119 interrupt *int32 120 noempty bool 121 timestamp int64 122 } 123 124 // intervalAdjust represents a resubmitting interval adjustment. 125 type intervalAdjust struct { 126 ratio float64 127 inc bool 128 } 129 130 // worker is the main object which takes care of submitting new work to consensus engine 131 // and gathering the sealing result. 132 type worker struct { 133 config *Config 134 chainConfig *params.ChainConfig 135 engine consensus.Engine 136 eth Backend 137 chain *core.BlockChain 138 139 // Feeds 140 pendingLogsFeed event.Feed 141 142 // Subscriptions 143 mux *event.TypeMux 144 txsCh chan core.NewTxsEvent 145 txsSub event.Subscription 146 chainHeadCh chan core.ChainHeadEvent 147 chainHeadSub event.Subscription 148 chainSideCh chan core.ChainSideEvent 149 chainSideSub event.Subscription 150 151 // Channels 152 newWorkCh chan *newWorkReq 153 taskCh chan *task 154 resultCh chan *types.Block 155 startCh chan struct{} 156 exitCh chan struct{} 157 resubmitIntervalCh chan time.Duration 158 resubmitAdjustCh chan *intervalAdjust 159 160 current *environment // An environment for current running cycle. 161 localUncles map[common.Hash]*types.Block // A set of side blocks generated locally as the possible uncle blocks. 162 remoteUncles map[common.Hash]*types.Block // A set of side blocks as the possible uncle blocks. 163 unconfirmed *unconfirmedBlocks // A set of locally mined blocks pending canonicalness confirmations. 164 165 mu sync.RWMutex // The lock used to protect the coinbase and extra fields 166 coinbase common.Address 167 extra []byte 168 169 pendingMu sync.RWMutex 170 pendingTasks map[common.Hash]*task 171 172 snapshotMu sync.RWMutex // The lock used to protect the block snapshot and state snapshot 173 snapshotBlock *types.Block 174 snapshotState *state.StateDB 175 176 // atomic status counters 177 running int32 // The indicator whether the consensus engine is running or not. 178 newTxs int32 // New arrival transaction count since last sealing work submitting. 179 180 // noempty is the flag used to control whether the feature of pre-seal empty 181 // block is enabled. The default value is false(pre-seal is enabled by default). 182 // But in some special scenario the consensus engine will seal blocks instantaneously, 183 // in this case this feature will add all empty blocks into canonical chain 184 // non-stop and no real transaction will be included. 185 noempty uint32 186 187 // External functions 188 isLocalBlock func(block *types.Block) bool // Function used to determine whether the specified block is mined by local miner. 189 190 // Test hooks 191 newTaskHook func(*task) // Method to call upon receiving a new sealing task. 192 skipSealHook func(*task) bool // Method to decide whether skipping the sealing. 193 fullTaskHook func() // Method to call before pushing the full sealing task. 194 resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval. 195 } 196 197 func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, isLocalBlock func(*types.Block) bool, init bool) *worker { 198 worker := &worker{ 199 config: config, 200 chainConfig: chainConfig, 201 engine: engine, 202 eth: eth, 203 mux: mux, 204 chain: eth.BlockChain(), 205 isLocalBlock: isLocalBlock, 206 localUncles: make(map[common.Hash]*types.Block), 207 remoteUncles: make(map[common.Hash]*types.Block), 208 unconfirmed: newUnconfirmedBlocks(eth.BlockChain(), miningLogAtDepth), 209 pendingTasks: make(map[common.Hash]*task), 210 txsCh: make(chan core.NewTxsEvent, txChanSize), 211 chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), 212 chainSideCh: make(chan core.ChainSideEvent, chainSideChanSize), 213 newWorkCh: make(chan *newWorkReq), 214 taskCh: make(chan *task), 215 resultCh: make(chan *types.Block, resultQueueSize), 216 exitCh: make(chan struct{}), 217 startCh: make(chan struct{}, 1), 218 resubmitIntervalCh: make(chan time.Duration), 219 resubmitAdjustCh: make(chan *intervalAdjust, resubmitAdjustChanSize), 220 } 221 // Subscribe NewTxsEvent for tx pool 222 worker.txsSub = eth.TxPool().SubscribeNewTxsEvent(worker.txsCh) 223 // Subscribe events for blockchain 224 worker.chainHeadSub = eth.BlockChain().SubscribeChainHeadEvent(worker.chainHeadCh) 225 worker.chainSideSub = eth.BlockChain().SubscribeChainSideEvent(worker.chainSideCh) 226 227 // Sanitize recommit interval if the user-specified one is too short. 228 recommit := worker.config.Recommit 229 if recommit < minRecommitInterval { 230 log.Warn("Sanitizing miner recommit interval", "provided", recommit, "updated", minRecommitInterval) 231 recommit = minRecommitInterval 232 } 233 234 go worker.mainLoop() 235 go worker.newWorkLoop(recommit) 236 go worker.resultLoop() 237 go worker.taskLoop() 238 239 // Submit first work to initialize pending state. 240 if init { 241 worker.startCh <- struct{}{} 242 } 243 return worker 244 } 245 246 // setEtherbase sets the etherbase used to initialize the block coinbase field. 247 func (w *worker) setEtherbase(addr common.Address) { 248 w.mu.Lock() 249 defer w.mu.Unlock() 250 w.coinbase = addr 251 } 252 253 // setExtra sets the content used to initialize the block extra field. 254 func (w *worker) setExtra(extra []byte) { 255 w.mu.Lock() 256 defer w.mu.Unlock() 257 w.extra = extra 258 } 259 260 // setRecommitInterval updates the interval for miner sealing work recommitting. 261 func (w *worker) setRecommitInterval(interval time.Duration) { 262 w.resubmitIntervalCh <- interval 263 } 264 265 // disablePreseal disables pre-sealing mining feature 266 func (w *worker) disablePreseal() { 267 atomic.StoreUint32(&w.noempty, 1) 268 } 269 270 // enablePreseal enables pre-sealing mining feature 271 func (w *worker) enablePreseal() { 272 atomic.StoreUint32(&w.noempty, 0) 273 } 274 275 // pending returns the pending state and corresponding block. 276 func (w *worker) pending() (*types.Block, *state.StateDB) { 277 // return a snapshot to avoid contention on currentMu mutex 278 w.snapshotMu.RLock() 279 defer w.snapshotMu.RUnlock() 280 if w.snapshotState == nil { 281 return nil, nil 282 } 283 return w.snapshotBlock, w.snapshotState.Copy() 284 } 285 286 // pendingBlock returns pending block. 287 func (w *worker) pendingBlock() *types.Block { 288 // return a snapshot to avoid contention on currentMu mutex 289 w.snapshotMu.RLock() 290 defer w.snapshotMu.RUnlock() 291 return w.snapshotBlock 292 } 293 294 // start sets the running status as 1 and triggers new work submitting. 295 func (w *worker) start() { 296 atomic.StoreInt32(&w.running, 1) 297 w.startCh <- struct{}{} 298 } 299 300 // stop sets the running status as 0. 301 func (w *worker) stop() { 302 atomic.StoreInt32(&w.running, 0) 303 } 304 305 // isRunning returns an indicator whether worker is running or not. 306 func (w *worker) isRunning() bool { 307 return atomic.LoadInt32(&w.running) == 1 308 } 309 310 // close terminates all background threads maintained by the worker. 311 // Note the worker does not support being closed multiple times. 312 func (w *worker) close() { 313 if w.current != nil && w.current.state != nil { 314 w.current.state.StopPrefetcher() 315 } 316 atomic.StoreInt32(&w.running, 0) 317 close(w.exitCh) 318 } 319 320 // recalcRecommit recalculates the resubmitting interval upon feedback. 321 func recalcRecommit(minRecommit, prev time.Duration, target float64, inc bool) time.Duration { 322 var ( 323 prevF = float64(prev.Nanoseconds()) 324 next float64 325 ) 326 if inc { 327 next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target+intervalAdjustBias) 328 max := float64(maxRecommitInterval.Nanoseconds()) 329 if next > max { 330 next = max 331 } 332 } else { 333 next = prevF*(1-intervalAdjustRatio) + intervalAdjustRatio*(target-intervalAdjustBias) 334 min := float64(minRecommit.Nanoseconds()) 335 if next < min { 336 next = min 337 } 338 } 339 return time.Duration(int64(next)) 340 } 341 342 // newWorkLoop is a standalone goroutine to submit new mining work upon received events. 343 func (w *worker) newWorkLoop(recommit time.Duration) { 344 var ( 345 interrupt *int32 346 minRecommit = recommit // minimal resubmit interval specified by user. 347 timestamp int64 // timestamp for each round of mining. 348 ) 349 350 timer := time.NewTimer(0) 351 defer timer.Stop() 352 <-timer.C // discard the initial tick 353 354 // commit aborts in-flight transaction execution with given signal and resubmits a new one. 355 commit := func(noempty bool, s int32) { 356 if interrupt != nil { 357 atomic.StoreInt32(interrupt, s) 358 } 359 interrupt = new(int32) 360 select { 361 case w.newWorkCh <- &newWorkReq{interrupt: interrupt, noempty: noempty, timestamp: timestamp}: 362 case <-w.exitCh: 363 return 364 } 365 timer.Reset(recommit) 366 atomic.StoreInt32(&w.newTxs, 0) 367 } 368 // clearPending cleans the stale pending tasks. 369 clearPending := func(number uint64) { 370 w.pendingMu.Lock() 371 for h, t := range w.pendingTasks { 372 if t.block.NumberU64()+staleThreshold <= number { 373 delete(w.pendingTasks, h) 374 } 375 } 376 w.pendingMu.Unlock() 377 } 378 379 for { 380 select { 381 case <-w.startCh: 382 clearPending(w.chain.CurrentBlock().NumberU64()) 383 timestamp = time.Now().Unix() 384 commit(true, commitInterruptNewHead) 385 386 case head := <-w.chainHeadCh: 387 if !w.isRunning() { 388 continue 389 } 390 clearPending(head.Block.NumberU64()) 391 timestamp = time.Now().Unix() 392 if p, ok := w.engine.(*parlia.Parlia); ok { 393 signedRecent, err := p.SignRecently(w.chain, head.Block.Header()) 394 if err != nil { 395 log.Info("Not allowed to propose block", "err", err) 396 continue 397 } 398 if signedRecent { 399 log.Info("Signed recently, must wait") 400 continue 401 } 402 } 403 commit(true, commitInterruptNewHead) 404 405 case <-timer.C: 406 // If mining is running resubmit a new work cycle periodically to pull in 407 // higher priced transactions. Disable this overhead for pending blocks. 408 if w.isRunning() && ((w.chainConfig.Ethash != nil) || (w.chainConfig.Clique != nil && 409 w.chainConfig.Clique.Period > 0) || (w.chainConfig.Parlia != nil && w.chainConfig.Parlia.Period > 0)) { 410 // Short circuit if no new transaction arrives. 411 if atomic.LoadInt32(&w.newTxs) == 0 { 412 timer.Reset(recommit) 413 continue 414 } 415 commit(true, commitInterruptResubmit) 416 } 417 418 case interval := <-w.resubmitIntervalCh: 419 // Adjust resubmit interval explicitly by user. 420 if interval < minRecommitInterval { 421 log.Warn("Sanitizing miner recommit interval", "provided", interval, "updated", minRecommitInterval) 422 interval = minRecommitInterval 423 } 424 log.Info("Miner recommit interval update", "from", minRecommit, "to", interval) 425 minRecommit, recommit = interval, interval 426 427 if w.resubmitHook != nil { 428 w.resubmitHook(minRecommit, recommit) 429 } 430 431 case adjust := <-w.resubmitAdjustCh: 432 // Adjust resubmit interval by feedback. 433 if adjust.inc { 434 before := recommit 435 target := float64(recommit.Nanoseconds()) / adjust.ratio 436 recommit = recalcRecommit(minRecommit, recommit, target, true) 437 log.Trace("Increase miner recommit interval", "from", before, "to", recommit) 438 } else { 439 before := recommit 440 recommit = recalcRecommit(minRecommit, recommit, float64(minRecommit.Nanoseconds()), false) 441 log.Trace("Decrease miner recommit interval", "from", before, "to", recommit) 442 } 443 444 if w.resubmitHook != nil { 445 w.resubmitHook(minRecommit, recommit) 446 } 447 448 case <-w.exitCh: 449 return 450 } 451 } 452 } 453 454 // mainLoop is a standalone goroutine to regenerate the sealing task based on the received event. 455 func (w *worker) mainLoop() { 456 defer w.txsSub.Unsubscribe() 457 defer w.chainHeadSub.Unsubscribe() 458 defer w.chainSideSub.Unsubscribe() 459 460 for { 461 select { 462 case req := <-w.newWorkCh: 463 w.commitNewWork(req.interrupt, req.noempty, req.timestamp) 464 465 case ev := <-w.chainSideCh: 466 // Short circuit for duplicate side blocks 467 if _, ok := w.engine.(*parlia.Parlia); ok { 468 continue 469 } 470 if _, exist := w.localUncles[ev.Block.Hash()]; exist { 471 continue 472 } 473 if _, exist := w.remoteUncles[ev.Block.Hash()]; exist { 474 continue 475 } 476 // Add side block to possible uncle block set depending on the author. 477 if w.isLocalBlock != nil && w.isLocalBlock(ev.Block) { 478 w.localUncles[ev.Block.Hash()] = ev.Block 479 } else { 480 w.remoteUncles[ev.Block.Hash()] = ev.Block 481 } 482 // If our mining block contains less than 2 uncle blocks, 483 // add the new uncle block if valid and regenerate a mining block. 484 if w.isRunning() && w.current != nil && w.current.uncles.Cardinality() < 2 { 485 start := time.Now() 486 if err := w.commitUncle(w.current, ev.Block.Header()); err == nil { 487 var uncles []*types.Header 488 w.commit(uncles, nil, false, start) 489 } 490 } 491 492 case ev := <-w.txsCh: 493 // Apply transactions to the pending state if we're not mining. 494 // 495 // Note all transactions received may not be continuous with transactions 496 // already included in the current mining block. These transactions will 497 // be automatically eliminated. 498 if !w.isRunning() && w.current != nil { 499 // If block is already full, abort 500 if gp := w.current.gasPool; gp != nil && gp.Gas() < params.TxGas { 501 continue 502 } 503 w.mu.RLock() 504 coinbase := w.coinbase 505 w.mu.RUnlock() 506 507 txs := make(map[common.Address]types.Transactions) 508 for _, tx := range ev.Txs { 509 acc, _ := types.Sender(w.current.signer, tx) 510 txs[acc] = append(txs[acc], tx) 511 } 512 txset := types.NewTransactionsByPriceAndNonce(w.current.signer, txs) 513 tcount := w.current.tcount 514 w.commitTransactions(txset, coinbase, nil) 515 // Only update the snapshot if any new transactons were added 516 // to the pending block 517 if tcount != w.current.tcount { 518 w.updateSnapshot() 519 } 520 } else { 521 // Special case, if the consensus engine is 0 period clique(dev mode), 522 // submit mining work here since all empty submission will be rejected 523 // by clique. Of course the advance sealing(empty submission) is disabled. 524 if (w.chainConfig.Clique != nil && w.chainConfig.Clique.Period == 0) || 525 (w.chainConfig.Parlia != nil && w.chainConfig.Parlia.Period == 0) { 526 w.commitNewWork(nil, true, time.Now().Unix()) 527 } 528 } 529 atomic.AddInt32(&w.newTxs, int32(len(ev.Txs))) 530 531 // System stopped 532 case <-w.exitCh: 533 return 534 case <-w.txsSub.Err(): 535 return 536 case <-w.chainHeadSub.Err(): 537 return 538 case <-w.chainSideSub.Err(): 539 return 540 } 541 } 542 } 543 544 // taskLoop is a standalone goroutine to fetch sealing task from the generator and 545 // push them to consensus engine. 546 func (w *worker) taskLoop() { 547 var ( 548 stopCh chan struct{} 549 prev common.Hash 550 ) 551 552 // interrupt aborts the in-flight sealing task. 553 interrupt := func() { 554 if stopCh != nil { 555 close(stopCh) 556 stopCh = nil 557 } 558 } 559 for { 560 select { 561 case task := <-w.taskCh: 562 if w.newTaskHook != nil { 563 w.newTaskHook(task) 564 } 565 // Reject duplicate sealing work due to resubmitting. 566 sealHash := w.engine.SealHash(task.block.Header()) 567 if sealHash == prev { 568 continue 569 } 570 // Interrupt previous sealing operation 571 interrupt() 572 stopCh, prev = make(chan struct{}), sealHash 573 574 if w.skipSealHook != nil && w.skipSealHook(task) { 575 continue 576 } 577 w.pendingMu.Lock() 578 w.pendingTasks[sealHash] = task 579 w.pendingMu.Unlock() 580 581 if err := w.engine.Seal(w.chain, task.block, w.resultCh, stopCh); err != nil { 582 log.Warn("Block sealing failed", "err", err) 583 } 584 case <-w.exitCh: 585 interrupt() 586 return 587 } 588 } 589 } 590 591 // resultLoop is a standalone goroutine to handle sealing result submitting 592 // and flush relative data to the database. 593 func (w *worker) resultLoop() { 594 for { 595 select { 596 case block := <-w.resultCh: 597 // Short circuit when receiving empty result. 598 if block == nil { 599 continue 600 } 601 // Short circuit when receiving duplicate result caused by resubmitting. 602 if w.chain.HasBlock(block.Hash(), block.NumberU64()) { 603 continue 604 } 605 var ( 606 sealhash = w.engine.SealHash(block.Header()) 607 hash = block.Hash() 608 ) 609 w.pendingMu.RLock() 610 task, exist := w.pendingTasks[sealhash] 611 w.pendingMu.RUnlock() 612 if !exist { 613 log.Error("Block found but no relative pending task", "number", block.Number(), "sealhash", sealhash, "hash", hash) 614 continue 615 } 616 // Different block could share same sealhash, deep copy here to prevent write-write conflict. 617 var ( 618 receipts = make([]*types.Receipt, len(task.receipts)) 619 logs []*types.Log 620 ) 621 for i, receipt := range task.receipts { 622 // add block location fields 623 receipt.BlockHash = hash 624 receipt.BlockNumber = block.Number() 625 receipt.TransactionIndex = uint(i) 626 627 receipts[i] = new(types.Receipt) 628 *receipts[i] = *receipt 629 // Update the block hash in all logs since it is now available and not when the 630 // receipt/log of individual transactions were created. 631 for _, log := range receipt.Logs { 632 log.BlockHash = hash 633 } 634 logs = append(logs, receipt.Logs...) 635 } 636 // Commit block and state to database. 637 _, err := w.chain.WriteBlockWithState(block, receipts, logs, task.state, true) 638 if err != nil { 639 log.Error("Failed writing block to chain", "err", err) 640 continue 641 } 642 log.Info("Successfully sealed new block", "number", block.Number(), "sealhash", sealhash, "hash", hash, 643 "elapsed", common.PrettyDuration(time.Since(task.createdAt))) 644 645 // Broadcast the block and announce chain insertion event 646 w.mux.Post(core.NewMinedBlockEvent{Block: block}) 647 648 // Insert the block into the set of pending ones to resultLoop for confirmations 649 w.unconfirmed.Insert(block.NumberU64(), block.Hash()) 650 651 case <-w.exitCh: 652 return 653 } 654 } 655 } 656 657 // makeCurrent creates a new environment for the current cycle. 658 func (w *worker) makeCurrent(parent *types.Block, header *types.Header) error { 659 // Retrieve the parent state to execute on top and start a prefetcher for 660 // the miner to speed block sealing up a bit 661 state, err := w.chain.StateAt(parent.Root()) 662 if err != nil { 663 return err 664 } 665 state.StartPrefetcher("miner") 666 667 env := &environment{ 668 signer: types.MakeSigner(w.chainConfig, header.Number), 669 state: state, 670 ancestors: mapset.NewSet(), 671 family: mapset.NewSet(), 672 uncles: mapset.NewSet(), 673 header: header, 674 } 675 // Keep track of transactions which return errors so they can be removed 676 env.tcount = 0 677 678 // Swap out the old work with the new one, terminating any leftover prefetcher 679 // processes in the mean time and starting a new one. 680 if w.current != nil && w.current.state != nil { 681 w.current.state.StopPrefetcher() 682 } 683 w.current = env 684 return nil 685 } 686 687 // commitUncle adds the given block to uncle block set, returns error if failed to add. 688 func (w *worker) commitUncle(env *environment, uncle *types.Header) error { 689 hash := uncle.Hash() 690 if env.uncles.Contains(hash) { 691 return errors.New("uncle not unique") 692 } 693 if env.header.ParentHash == uncle.ParentHash { 694 return errors.New("uncle is sibling") 695 } 696 if !env.ancestors.Contains(uncle.ParentHash) { 697 return errors.New("uncle's parent unknown") 698 } 699 if env.family.Contains(hash) { 700 return errors.New("uncle already included") 701 } 702 env.uncles.Add(uncle.Hash()) 703 return nil 704 } 705 706 // updateSnapshot updates pending snapshot block and state. 707 // Note this function assumes the current variable is thread safe. 708 func (w *worker) updateSnapshot() { 709 w.snapshotMu.Lock() 710 defer w.snapshotMu.Unlock() 711 712 var uncles []*types.Header 713 w.current.uncles.Each(func(item interface{}) bool { 714 hash, ok := item.(common.Hash) 715 if !ok { 716 return false 717 } 718 uncle, exist := w.localUncles[hash] 719 if !exist { 720 uncle, exist = w.remoteUncles[hash] 721 } 722 if !exist { 723 return false 724 } 725 uncles = append(uncles, uncle.Header()) 726 return false 727 }) 728 729 w.snapshotBlock = types.NewBlock( 730 w.current.header, 731 w.current.txs, 732 uncles, 733 w.current.receipts, 734 trie.NewStackTrie(nil), 735 ) 736 w.snapshotState = w.current.state.Copy() 737 } 738 739 func (w *worker) commitTransaction(tx *types.Transaction, coinbase common.Address, receiptProcessors ...core.ReceiptProcessor) ([]*types.Log, error) { 740 snap := w.current.state.Snapshot() 741 742 receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &coinbase, w.current.gasPool, w.current.state, w.current.header, tx, &w.current.header.GasUsed, *w.chain.GetVMConfig(), receiptProcessors...) 743 if err != nil { 744 w.current.state.RevertToSnapshot(snap) 745 return nil, err 746 } 747 w.current.txs = append(w.current.txs, tx) 748 w.current.receipts = append(w.current.receipts, receipt) 749 750 return receipt.Logs, nil 751 } 752 753 func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coinbase common.Address, interrupt *int32) bool { 754 // Short circuit if current is nil 755 if w.current == nil { 756 return true 757 } 758 759 if w.current.gasPool == nil { 760 w.current.gasPool = new(core.GasPool).AddGas(w.current.header.GasLimit) 761 w.current.gasPool.SubGas(params.SystemTxsGas) 762 } 763 764 var coalescedLogs []*types.Log 765 var stopTimer *time.Timer 766 delay := w.engine.Delay(w.chain, w.current.header) 767 if delay != nil { 768 stopTimer = time.NewTimer(*delay - w.config.DelayLeftOver) 769 log.Debug("Time left for mining work", "left", (*delay - w.config.DelayLeftOver).String(), "leftover", w.config.DelayLeftOver) 770 defer stopTimer.Stop() 771 } 772 773 // initilise bloom processors 774 processorCapacity := 100 775 if txs.CurrentSize() < processorCapacity { 776 processorCapacity = txs.CurrentSize() 777 } 778 bloomProcessors := core.NewAsyncReceiptBloomGenerator(processorCapacity) 779 780 LOOP: 781 for { 782 // In the following three cases, we will interrupt the execution of the transaction. 783 // (1) new head block event arrival, the interrupt signal is 1 784 // (2) worker start or restart, the interrupt signal is 1 785 // (3) worker recreate the mining block with any newly arrived transactions, the interrupt signal is 2. 786 // For the first two cases, the semi-finished work will be discarded. 787 // For the third case, the semi-finished work will be submitted to the consensus engine. 788 if interrupt != nil && atomic.LoadInt32(interrupt) != commitInterruptNone { 789 // Notify resubmit loop to increase resubmitting interval due to too frequent commits. 790 if atomic.LoadInt32(interrupt) == commitInterruptResubmit { 791 ratio := float64(w.current.header.GasLimit-w.current.gasPool.Gas()) / float64(w.current.header.GasLimit) 792 if ratio < 0.1 { 793 ratio = 0.1 794 } 795 w.resubmitAdjustCh <- &intervalAdjust{ 796 ratio: ratio, 797 inc: true, 798 } 799 } 800 return atomic.LoadInt32(interrupt) == commitInterruptNewHead 801 } 802 // If we don't have enough gas for any further transactions then we're done 803 if w.current.gasPool.Gas() < params.TxGas { 804 log.Trace("Not enough gas for further transactions", "have", w.current.gasPool, "want", params.TxGas) 805 break 806 } 807 if stopTimer != nil { 808 select { 809 case <-stopTimer.C: 810 log.Info("Not enough time for further transactions", "txs", len(w.current.txs)) 811 break LOOP 812 default: 813 } 814 } 815 // Retrieve the next transaction and abort if all done 816 tx := txs.Peek() 817 if tx == nil { 818 break 819 } 820 // Error may be ignored here. The error has already been checked 821 // during transaction acceptance is the transaction pool. 822 // 823 // We use the eip155 signer regardless of the current hf. 824 //from, _ := types.Sender(w.current.signer, tx) 825 // Check whether the tx is replay protected. If we're not in the EIP155 hf 826 // phase, start ignoring the sender until we do. 827 if tx.Protected() && !w.chainConfig.IsEIP155(w.current.header.Number) { 828 //log.Trace("Ignoring reply protected transaction", "hash", tx.Hash(), "eip155", w.chainConfig.EIP155Block) 829 txs.Pop() 830 continue 831 } 832 // Start executing the transaction 833 w.current.state.Prepare(tx.Hash(), common.Hash{}, w.current.tcount) 834 835 logs, err := w.commitTransaction(tx, coinbase, bloomProcessors) 836 switch { 837 case errors.Is(err, core.ErrGasLimitReached): 838 // Pop the current out-of-gas transaction without shifting in the next from the account 839 //log.Trace("Gas limit exceeded for current block", "sender", from) 840 txs.Pop() 841 842 case errors.Is(err, core.ErrNonceTooLow): 843 // New head notification data race between the transaction pool and miner, shift 844 //log.Trace("Skipping transaction with low nonce", "sender", from, "nonce", tx.Nonce()) 845 txs.Shift() 846 847 case errors.Is(err, core.ErrNonceTooHigh): 848 // Reorg notification data race between the transaction pool and miner, skip account = 849 //log.Trace("Skipping account with hight nonce", "sender", from, "nonce", tx.Nonce()) 850 txs.Pop() 851 852 case errors.Is(err, nil): 853 // Everything ok, collect the logs and shift in the next transaction from the same account 854 coalescedLogs = append(coalescedLogs, logs...) 855 w.current.tcount++ 856 txs.Shift() 857 858 case errors.Is(err, core.ErrTxTypeNotSupported): 859 // Pop the unsupported transaction without shifting in the next from the account 860 //log.Trace("Skipping unsupported transaction type", "sender", from, "type", tx.Type()) 861 txs.Pop() 862 863 default: 864 // Strange error, discard the transaction and get the next in line (note, the 865 // nonce-too-high clause will prevent us from executing in vain). 866 //log.Debug("Transaction failed, account skipped", "hash", tx.Hash(), "err", err) 867 txs.Shift() 868 } 869 } 870 bloomProcessors.Close() 871 872 if !w.isRunning() && len(coalescedLogs) > 0 { 873 // We don't push the pendingLogsEvent while we are mining. The reason is that 874 // when we are mining, the worker will regenerate a mining block every 3 seconds. 875 // In order to avoid pushing the repeated pendingLog, we disable the pending log pushing. 876 877 // make a copy, the state caches the logs and these logs get "upgraded" from pending to mined 878 // logs by filling in the block hash when the block was mined by the local miner. This can 879 // cause a race condition if a log was "upgraded" before the PendingLogsEvent is processed. 880 cpy := make([]*types.Log, len(coalescedLogs)) 881 for i, l := range coalescedLogs { 882 cpy[i] = new(types.Log) 883 *cpy[i] = *l 884 } 885 w.pendingLogsFeed.Send(cpy) 886 } 887 // Notify resubmit loop to decrease resubmitting interval if current interval is larger 888 // than the user-specified one. 889 if interrupt != nil { 890 w.resubmitAdjustCh <- &intervalAdjust{inc: false} 891 } 892 return false 893 } 894 895 // commitNewWork generates several new sealing tasks based on the parent block. 896 func (w *worker) commitNewWork(interrupt *int32, noempty bool, timestamp int64) { 897 w.mu.RLock() 898 defer w.mu.RUnlock() 899 900 tstart := time.Now() 901 parent := w.chain.CurrentBlock() 902 903 if parent.Time() >= uint64(timestamp) { 904 timestamp = int64(parent.Time() + 1) 905 } 906 num := parent.Number() 907 header := &types.Header{ 908 ParentHash: parent.Hash(), 909 Number: num.Add(num, common.Big1), 910 GasLimit: core.CalcGasLimit(parent, w.config.GasFloor, w.config.GasCeil), 911 Extra: w.extra, 912 Time: uint64(timestamp), 913 } 914 // Only set the coinbase if our consensus engine is running (avoid spurious block rewards) 915 if w.isRunning() { 916 if w.coinbase == (common.Address{}) { 917 log.Error("Refusing to mine without etherbase") 918 return 919 } 920 header.Coinbase = w.coinbase 921 } 922 if err := w.engine.Prepare(w.chain, header); err != nil { 923 log.Error("Failed to prepare header for mining", "err", err) 924 return 925 } 926 // If we are care about TheDAO hard-fork check whether to override the extra-data or not 927 if daoBlock := w.chainConfig.DAOForkBlock; daoBlock != nil { 928 // Check whether the block is among the fork extra-override range 929 limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange) 930 if header.Number.Cmp(daoBlock) >= 0 && header.Number.Cmp(limit) < 0 { 931 // Depending whether we support or oppose the fork, override differently 932 if w.chainConfig.DAOForkSupport { 933 header.Extra = common.CopyBytes(params.DAOForkBlockExtra) 934 } else if bytes.Equal(header.Extra, params.DAOForkBlockExtra) { 935 header.Extra = []byte{} // If miner opposes, don't let it use the reserved extra-data 936 } 937 } 938 } 939 // Could potentially happen if starting to mine in an odd state. 940 err := w.makeCurrent(parent, header) 941 if err != nil { 942 log.Error("Failed to create mining context", "err", err) 943 return 944 } 945 // Create the current work task and check any fork transitions needed 946 env := w.current 947 if w.chainConfig.DAOForkSupport && w.chainConfig.DAOForkBlock != nil && w.chainConfig.DAOForkBlock.Cmp(header.Number) == 0 { 948 misc.ApplyDAOHardFork(env.state) 949 } 950 systemcontracts.UpgradeBuildInSystemContract(w.chainConfig, header.Number, env.state) 951 // Accumulate the uncles for the current block 952 uncles := make([]*types.Header, 0) 953 // Create an empty block based on temporary copied state for 954 // sealing in advance without waiting block execution finished. 955 if !noempty && atomic.LoadUint32(&w.noempty) == 0 { 956 w.commit(uncles, nil, false, tstart) 957 } 958 959 // Fill the block with all available pending transactions. 960 pending, err := w.eth.TxPool().Pending() 961 if err != nil { 962 log.Error("Failed to fetch pending transactions", "err", err) 963 } 964 // Short circuit if there is no available pending transactions 965 if len(pending) != 0 { 966 start := time.Now() 967 // Split the pending transactions into locals and remotes 968 localTxs, remoteTxs := make(map[common.Address]types.Transactions), pending 969 for _, account := range w.eth.TxPool().Locals() { 970 if txs := remoteTxs[account]; len(txs) > 0 { 971 delete(remoteTxs, account) 972 localTxs[account] = txs 973 } 974 } 975 if len(localTxs) > 0 { 976 txs := types.NewTransactionsByPriceAndNonce(w.current.signer, localTxs) 977 if w.commitTransactions(txs, w.coinbase, interrupt) { 978 return 979 } 980 } 981 if len(remoteTxs) > 0 { 982 txs := types.NewTransactionsByPriceAndNonce(w.current.signer, remoteTxs) 983 if w.commitTransactions(txs, w.coinbase, interrupt) { 984 return 985 } 986 } 987 commitTxsTimer.UpdateSince(start) 988 log.Info("Gas pool", "height", header.Number.String(), "pool", w.current.gasPool.String()) 989 } 990 w.commit(uncles, w.fullTaskHook, false, tstart) 991 } 992 993 // commit runs any post-transaction state modifications, assembles the final block 994 // and commits new work if consensus engine is running. 995 func (w *worker) commit(uncles []*types.Header, interval func(), update bool, start time.Time) error { 996 s := w.current.state 997 block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, types.CopyHeader(w.current.header), s, w.current.txs, uncles, w.current.receipts) 998 if err != nil { 999 return err 1000 } 1001 if w.isRunning() { 1002 if interval != nil { 1003 interval() 1004 } 1005 select { 1006 case w.taskCh <- &task{receipts: receipts, state: s, block: block, createdAt: time.Now()}: 1007 w.unconfirmed.Shift(block.NumberU64() - 1) 1008 log.Info("Commit new mining work", "number", block.Number(), "sealhash", w.engine.SealHash(block.Header()), 1009 "uncles", len(uncles), "txs", w.current.tcount, 1010 "gas", block.GasUsed(), 1011 "elapsed", common.PrettyDuration(time.Since(start))) 1012 1013 case <-w.exitCh: 1014 log.Info("Worker has exited") 1015 } 1016 } 1017 if update { 1018 w.updateSnapshot() 1019 } 1020 return nil 1021 } 1022 1023 // postSideBlock fires a side chain event, only use it for testing. 1024 func (w *worker) postSideBlock(event core.ChainSideEvent) { 1025 select { 1026 case w.chainSideCh <- event: 1027 case <-w.exitCh: 1028 } 1029 }