2015-07-07 00:54:22 +00:00
// Copyright 2015 The go-ethereum Authors
2015-07-22 16:48:40 +00:00
// This file is part of the go-ethereum library.
2015-07-07 00:54:22 +00:00
//
2015-07-23 16:35:11 +00:00
// The go-ethereum library is free software: you can redistribute it and/or modify
2015-07-07 00:54:22 +00:00
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
2015-07-22 16:48:40 +00:00
// The go-ethereum library is distributed in the hope that it will be useful,
2015-07-07 00:54:22 +00:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
2015-07-22 16:48:40 +00:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-07 00:54:22 +00:00
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
2015-07-22 16:48:40 +00:00
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
2015-07-07 00:54:22 +00:00
2015-02-04 13:52:59 +00:00
package miner
import (
2016-07-08 15:48:17 +00:00
"bytes"
2015-02-04 13:52:59 +00:00
"fmt"
"math/big"
2015-02-15 15:16:27 +00:00
"sync"
2015-03-26 16:45:03 +00:00
"sync/atomic"
2015-06-15 09:33:08 +00:00
"time"
2015-02-04 13:52:59 +00:00
2018-07-16 07:54:19 +00:00
mapset "github.com/deckarep/golang-set"
2015-03-18 12:00:01 +00:00
"github.com/ethereum/go-ethereum/common"
2017-04-04 22:16:29 +00:00
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
2015-02-04 13:52:59 +00:00
"github.com/ethereum/go-ethereum/core"
2015-03-23 17:27:05 +00:00
"github.com/ethereum/go-ethereum/core/state"
2015-02-04 13:52:59 +00:00
"github.com/ethereum/go-ethereum/core/types"
2015-08-30 08:19:10 +00:00
"github.com/ethereum/go-ethereum/core/vm"
2015-09-14 07:35:57 +00:00
"github.com/ethereum/go-ethereum/ethdb"
2015-02-04 13:52:59 +00:00
"github.com/ethereum/go-ethereum/event"
2017-02-22 12:10:07 +00:00
"github.com/ethereum/go-ethereum/log"
2016-07-08 10:00:37 +00:00
"github.com/ethereum/go-ethereum/params"
2015-02-04 13:52:59 +00:00
)
2015-07-11 18:45:59 +00:00
const (
resultQueueSize = 10
miningLogAtDepth = 5
2017-08-18 10:58:36 +00:00
2018-05-18 08:45:52 +00:00
// txChanSize is the size of channel listening to NewTxsEvent.
2017-08-18 10:58:36 +00:00
// The number is referenced from the size of tx pool.
txChanSize = 4096
// chainHeadChanSize is the size of channel listening to ChainHeadEvent.
chainHeadChanSize = 10
// chainSideChanSize is the size of channel listening to ChainSideEvent.
chainSideChanSize = 10
2015-07-11 18:45:59 +00:00
)
2015-05-11 19:47:34 +00:00
// Agent can register themself with the worker
type Agent interface {
2015-07-11 18:45:59 +00:00
Work ( ) chan <- * Work
SetReturnCh ( chan <- * Result )
2015-05-11 19:47:34 +00:00
Start ( )
2018-08-03 08:33:37 +00:00
Stop ( )
2015-05-11 19:47:34 +00:00
}
2016-08-15 18:14:05 +00:00
// Work is the workers current environment and holds
2015-05-11 19:47:34 +00:00
// all of the current state information
2015-07-11 18:45:59 +00:00
type Work struct {
2016-11-02 12:44:13 +00:00
config * params . ChainConfig
signer types . Signer
2017-05-16 19:07:27 +00:00
state * state . StateDB // apply state changes here
2018-07-16 07:54:19 +00:00
ancestors mapset . Set // ancestor set (used for checking uncle parent validity)
family mapset . Set // family set (used for checking uncle invalidity)
uncles mapset . Set // uncle set
2017-05-16 19:07:27 +00:00
tcount int // tx count in cycle
2018-05-18 08:45:52 +00:00
gasPool * core . GasPool // available gas used to pack transactions
2015-02-04 13:52:59 +00:00
2015-07-11 18:45:59 +00:00
Block * types . Block // the new block
2015-02-04 13:52:59 +00:00
2015-06-16 10:41:50 +00:00
header * types . Header
txs [ ] * types . Transaction
receipts [ ] * types . Receipt
2015-07-11 18:45:59 +00:00
createdAt time . Time
}
type Result struct {
Work * Work
Block * types . Block
2015-02-04 13:52:59 +00:00
}
2015-05-11 19:47:34 +00:00
// worker is the main object which takes care of applying messages to the new state
2015-02-04 13:52:59 +00:00
type worker struct {
2016-10-20 11:36:29 +00:00
config * params . ChainConfig
2017-04-04 22:16:29 +00:00
engine consensus . Engine
2016-03-01 22:32:43 +00:00
2015-03-26 16:45:03 +00:00
mu sync . Mutex
2016-03-29 01:08:16 +00:00
// update loop
2017-08-18 10:58:36 +00:00
mux * event . TypeMux
2018-05-18 08:45:52 +00:00
txsCh chan core . NewTxsEvent
2018-05-10 07:04:45 +00:00
txsSub event . Subscription
2017-08-18 10:58:36 +00:00
chainHeadCh chan core . ChainHeadEvent
chainHeadSub event . Subscription
chainSideCh chan core . ChainSideEvent
chainSideSub event . Subscription
2016-03-29 01:08:16 +00:00
2015-10-29 12:28:00 +00:00
agents map [ Agent ] struct { }
2015-07-11 18:45:59 +00:00
recv chan * Result
2015-02-04 13:52:59 +00:00
2016-08-15 18:14:05 +00:00
eth Backend
2015-08-31 15:09:50 +00:00
chain * core . BlockChain
2015-10-19 14:08:17 +00:00
proc core . Validator
2015-09-14 07:35:57 +00:00
chainDb ethdb . Database
2015-04-05 16:57:03 +00:00
2015-03-18 12:00:01 +00:00
coinbase common . Address
2015-04-05 16:57:03 +00:00
extra [ ] byte
2015-02-04 13:52:59 +00:00
2015-04-07 10:32:55 +00:00
currentMu sync . Mutex
2015-07-11 18:45:59 +00:00
current * Work
2015-02-13 16:23:09 +00:00
2018-04-16 07:56:20 +00:00
snapshotMu sync . RWMutex
snapshotBlock * types . Block
snapshotState * state . StateDB
2015-03-23 11:12:49 +00:00
uncleMu sync . Mutex
possibleUncles map [ common . Hash ] * types . Block
2016-12-13 13:10:52 +00:00
unconfirmed * unconfirmedBlocks // set of locally mined blocks pending canonicalness confirmations
2016-12-13 11:23:12 +00:00
2015-04-22 08:58:43 +00:00
// atomic status counters
2018-08-03 08:33:37 +00:00
atWork int32 // The number of in-flight consensus engine work.
running int32 // The indicator whether the consensus engine is running or not.
2015-02-04 13:52:59 +00:00
}
2018-08-03 08:33:37 +00:00
func newWorker ( config * params . ChainConfig , engine consensus . Engine , eth Backend , mux * event . TypeMux ) * worker {
2015-04-07 10:32:55 +00:00
worker := & worker {
2016-03-01 22:32:43 +00:00
config : config ,
2017-04-04 22:16:29 +00:00
engine : engine ,
2015-03-23 11:12:49 +00:00
eth : eth ,
2016-08-15 18:14:05 +00:00
mux : mux ,
2018-05-18 08:45:52 +00:00
txsCh : make ( chan core . NewTxsEvent , txChanSize ) ,
2017-08-18 10:58:36 +00:00
chainHeadCh : make ( chan core . ChainHeadEvent , chainHeadChanSize ) ,
chainSideCh : make ( chan core . ChainSideEvent , chainSideChanSize ) ,
2015-08-06 17:57:39 +00:00
chainDb : eth . ChainDb ( ) ,
2015-07-11 18:45:59 +00:00
recv : make ( chan * Result , resultQueueSize ) ,
2015-08-31 15:09:50 +00:00
chain : eth . BlockChain ( ) ,
2015-10-19 14:08:17 +00:00
proc : eth . BlockChain ( ) . Validator ( ) ,
2015-03-23 11:12:49 +00:00
possibleUncles : make ( map [ common . Hash ] * types . Block ) ,
2015-10-29 12:28:00 +00:00
agents : make ( map [ Agent ] struct { } ) ,
2017-08-06 16:40:34 +00:00
unconfirmed : newUnconfirmedBlocks ( eth . BlockChain ( ) , miningLogAtDepth ) ,
2015-02-09 15:20:34 +00:00
}
2018-05-18 08:45:52 +00:00
// Subscribe NewTxsEvent for tx pool
worker . txsSub = eth . TxPool ( ) . SubscribeNewTxsEvent ( worker . txsCh )
2017-08-18 10:58:36 +00:00
// Subscribe events for blockchain
worker . chainHeadSub = eth . BlockChain ( ) . SubscribeChainHeadEvent ( worker . chainHeadCh )
worker . chainSideSub = eth . BlockChain ( ) . SubscribeChainSideEvent ( worker . chainSideCh )
2015-04-07 10:32:55 +00:00
go worker . update ( )
2016-03-29 01:08:16 +00:00
go worker . wait ( )
2015-04-07 10:32:55 +00:00
worker . commitNewWork ( )
return worker
2015-02-09 15:20:34 +00:00
}
2015-07-07 08:58:47 +00:00
func ( self * worker ) setEtherbase ( addr common . Address ) {
self . mu . Lock ( )
defer self . mu . Unlock ( )
self . coinbase = addr
}
2016-12-13 12:03:18 +00:00
func ( self * worker ) setExtra ( extra [ ] byte ) {
self . mu . Lock ( )
defer self . mu . Unlock ( )
self . extra = extra
}
2016-03-16 09:20:02 +00:00
func ( self * worker ) pending ( ) ( * types . Block , * state . StateDB ) {
2018-08-03 08:33:37 +00:00
// return a snapshot to avoid contention on currentMu mutex
self . snapshotMu . RLock ( )
defer self . snapshotMu . RUnlock ( )
return self . snapshotBlock , self . snapshotState . Copy ( )
2018-04-16 07:56:20 +00:00
}
2016-11-30 09:48:48 +00:00
2018-04-16 07:56:20 +00:00
func ( self * worker ) pendingBlock ( ) * types . Block {
2018-08-03 08:33:37 +00:00
// return a snapshot to avoid contention on currentMu mutex
self . snapshotMu . RLock ( )
defer self . snapshotMu . RUnlock ( )
return self . snapshotBlock
2016-11-30 09:48:48 +00:00
}
2015-04-07 10:32:55 +00:00
func ( self * worker ) start ( ) {
2015-05-09 10:32:36 +00:00
self . mu . Lock ( )
defer self . mu . Unlock ( )
2018-08-03 08:33:37 +00:00
atomic . StoreInt32 ( & self . running , 1 )
2015-10-29 12:28:00 +00:00
for agent := range self . agents {
2015-02-14 15:52:14 +00:00
agent . Start ( )
}
2015-02-09 15:20:34 +00:00
}
func ( self * worker ) stop ( ) {
2015-05-09 10:32:36 +00:00
self . mu . Lock ( )
defer self . mu . Unlock ( )
2018-08-03 08:33:37 +00:00
atomic . StoreInt32 ( & self . running , 0 )
for agent := range self . agents {
agent . Stop ( )
2015-04-07 22:30:23 +00:00
}
2015-04-22 08:58:43 +00:00
atomic . StoreInt32 ( & self . atWork , 0 )
2015-02-09 15:20:34 +00:00
}
2018-08-03 08:33:37 +00:00
func ( self * worker ) isRunning ( ) bool {
return atomic . LoadInt32 ( & self . running ) == 1
}
2015-02-09 15:20:34 +00:00
func ( self * worker ) register ( agent Agent ) {
2015-05-09 10:32:36 +00:00
self . mu . Lock ( )
defer self . mu . Unlock ( )
2015-10-29 12:28:00 +00:00
self . agents [ agent ] = struct { } { }
2015-03-24 09:34:06 +00:00
agent . SetReturnCh ( self . recv )
2018-08-03 08:33:37 +00:00
if self . isRunning ( ) {
agent . Start ( )
}
2015-02-04 13:52:59 +00:00
}
2015-10-29 12:28:00 +00:00
func ( self * worker ) unregister ( agent Agent ) {
self . mu . Lock ( )
defer self . mu . Unlock ( )
delete ( self . agents , agent )
agent . Stop ( )
}
2015-02-04 13:52:59 +00:00
func ( self * worker ) update ( ) {
2018-05-10 07:04:45 +00:00
defer self . txsSub . Unsubscribe ( )
2017-08-18 10:58:36 +00:00
defer self . chainHeadSub . Unsubscribe ( )
defer self . chainSideSub . Unsubscribe ( )
for {
2016-03-29 01:08:16 +00:00
// A real event arrived, process interesting content
2017-08-18 10:58:36 +00:00
select {
// Handle ChainHeadEvent
case <- self . chainHeadCh :
2016-03-29 01:08:16 +00:00
self . commitNewWork ( )
2017-08-18 10:58:36 +00:00
// Handle ChainSideEvent
case ev := <- self . chainSideCh :
2016-03-29 01:08:16 +00:00
self . uncleMu . Lock ( )
self . possibleUncles [ ev . Block . Hash ( ) ] = ev . Block
self . uncleMu . Unlock ( )
2017-08-18 10:58:36 +00:00
2018-05-18 08:45:52 +00:00
// Handle NewTxsEvent
2018-05-10 07:04:45 +00:00
case ev := <- self . txsCh :
// Apply transactions to the pending state if we're not mining.
//
// Note all transactions received may not be continuous with transactions
// already included in the current mining block. These transactions will
// be automatically eliminated.
2018-08-03 08:33:37 +00:00
if ! self . isRunning ( ) {
2016-03-29 01:08:16 +00:00
self . currentMu . Lock ( )
2018-05-10 07:04:45 +00:00
txs := make ( map [ common . Address ] types . Transactions )
for _ , tx := range ev . Txs {
acc , _ := types . Sender ( self . current . signer , tx )
txs [ acc ] = append ( txs [ acc ] , tx )
}
2017-09-07 21:22:27 +00:00
txset := types . NewTransactionsByPriceAndNonce ( self . current . signer , txs )
2017-05-16 19:07:27 +00:00
self . current . commitTransactions ( self . mux , txset , self . chain , self . coinbase )
2018-04-16 07:56:20 +00:00
self . updateSnapshot ( )
2016-03-29 01:08:16 +00:00
self . currentMu . Unlock ( )
2017-10-24 10:40:42 +00:00
} else {
// If we're mining, but nothing is being processed, wake on new transactions
if self . config . Clique != nil && self . config . Clique . Period == 0 {
self . commitNewWork ( )
}
2015-02-04 13:52:59 +00:00
}
2017-08-18 10:58:36 +00:00
// System stopped
2018-05-10 07:04:45 +00:00
case <- self . txsSub . Err ( ) :
2017-08-18 10:58:36 +00:00
return
case <- self . chainHeadSub . Err ( ) :
return
case <- self . chainSideSub . Err ( ) :
return
2015-02-04 13:52:59 +00:00
}
}
}
2015-02-09 15:20:34 +00:00
func ( self * worker ) wait ( ) {
for {
2015-07-11 18:45:59 +00:00
for result := range self . recv {
2015-04-22 08:58:43 +00:00
atomic . AddInt32 ( & self . atWork , - 1 )
2015-03-26 16:45:03 +00:00
2015-07-11 18:45:59 +00:00
if result == nil {
2015-03-26 16:45:03 +00:00
continue
}
2015-07-11 18:45:59 +00:00
block := result . Block
2015-08-04 18:38:57 +00:00
work := result . Work
2015-03-26 16:45:03 +00:00
2017-09-11 10:13:05 +00:00
// Update the block hash in all logs since it is now available and not when the
// receipt/log of individual transactions were created.
for _ , r := range work . receipts {
for _ , l := range r . Logs {
l . BlockHash = block . Hash ( )
2015-07-11 18:45:59 +00:00
}
2015-07-03 09:24:42 +00:00
}
2017-09-11 10:13:05 +00:00
for _ , log := range work . state . Logs ( ) {
log . BlockHash = block . Hash ( )
}
2018-07-31 07:22:33 +00:00
self . currentMu . Lock ( )
2018-02-05 16:40:32 +00:00
stat , err := self . chain . WriteBlockWithState ( block , work . receipts , work . state )
2018-07-31 07:22:33 +00:00
self . currentMu . Unlock ( )
2017-09-11 10:13:05 +00:00
if err != nil {
log . Error ( "Failed writing block to chain" , "err" , err )
continue
}
// Broadcast the block and announce chain insertion event
self . mux . Post ( core . NewMinedBlockEvent { Block : block } )
var (
events [ ] interface { }
logs = work . state . Logs ( )
)
events = append ( events , core . ChainEvent { Block : block , Hash : block . Hash ( ) , Logs : logs } )
if stat == core . CanonStatTy {
events = append ( events , core . ChainHeadEvent { Block : block } )
}
self . chain . PostChainEvents ( events , logs )
2016-12-13 11:23:12 +00:00
// Insert the block into the set of pending ones to wait for confirmations
2016-12-13 13:10:52 +00:00
self . unconfirmed . Insert ( block . NumberU64 ( ) , block . Hash ( ) )
2015-02-09 15:20:34 +00:00
}
}
}
2016-04-04 10:18:34 +00:00
// push sends a new work task to currently live miner agents.
2015-08-04 18:38:57 +00:00
func ( self * worker ) push ( work * Work ) {
2016-04-04 10:18:34 +00:00
for agent := range self . agents {
atomic . AddInt32 ( & self . atWork , 1 )
if ch := agent . Work ( ) ; ch != nil {
ch <- work
2015-02-13 16:23:09 +00:00
}
2015-02-04 13:52:59 +00:00
}
}
2015-06-16 10:41:50 +00:00
// makeCurrent creates a new environment for the current cycle.
2015-10-06 14:35:55 +00:00
func ( self * worker ) makeCurrent ( parent * types . Block , header * types . Header ) error {
2016-09-27 10:13:13 +00:00
state , err := self . chain . StateAt ( parent . Root ( ) )
2015-10-06 14:35:55 +00:00
if err != nil {
return err
}
2015-08-04 18:38:57 +00:00
work := & Work {
2016-03-01 22:32:43 +00:00
config : self . config ,
2018-06-05 10:31:34 +00:00
signer : types . NewEIP155Signer ( self . config . ChainID ) ,
2015-06-16 10:41:50 +00:00
state : state ,
2018-07-16 07:54:19 +00:00
ancestors : mapset . NewSet ( ) ,
family : mapset . NewSet ( ) ,
uncles : mapset . NewSet ( ) ,
2015-06-16 10:41:50 +00:00
header : header ,
2015-07-11 18:45:59 +00:00
createdAt : time . Now ( ) ,
2015-04-04 11:27:17 +00:00
}
2015-03-05 08:14:58 +00:00
2015-05-18 14:31:26 +00:00
// when 08 is processed ancestors contain 07 (quick block)
2015-06-16 10:41:50 +00:00
for _ , ancestor := range self . chain . GetBlocksFromHash ( parent . Hash ( ) , 7 ) {
2015-05-14 00:46:23 +00:00
for _ , uncle := range ancestor . Uncles ( ) {
2015-08-04 18:38:57 +00:00
work . family . Add ( uncle . Hash ( ) )
2015-05-14 00:46:23 +00:00
}
2015-08-04 18:38:57 +00:00
work . family . Add ( ancestor . Hash ( ) )
work . ancestors . Add ( ancestor . Hash ( ) )
2015-03-23 11:12:49 +00:00
}
2017-08-06 16:40:34 +00:00
2015-05-10 23:28:15 +00:00
// Keep track of transactions which return errors so they can be removed
2015-08-04 18:38:57 +00:00
work . tcount = 0
self . current = work
2015-10-06 14:35:55 +00:00
return nil
2015-04-07 10:32:55 +00:00
}
func ( self * worker ) commitNewWork ( ) {
self . mu . Lock ( )
defer self . mu . Unlock ( )
self . uncleMu . Lock ( )
defer self . uncleMu . Unlock ( )
self . currentMu . Lock ( )
defer self . currentMu . Unlock ( )
2015-06-15 09:33:08 +00:00
tstart := time . Now ( )
2015-06-16 10:41:50 +00:00
parent := self . chain . CurrentBlock ( )
2016-11-28 13:59:06 +00:00
2015-06-16 10:41:50 +00:00
tstamp := tstart . Unix ( )
2015-09-02 21:24:17 +00:00
if parent . Time ( ) . Cmp ( new ( big . Int ) . SetInt64 ( tstamp ) ) >= 0 {
2015-08-24 00:52:53 +00:00
tstamp = parent . Time ( ) . Int64 ( ) + 1
2015-06-16 10:41:50 +00:00
}
2015-06-29 16:55:49 +00:00
// this will ensure we're not going off too far in the future
2017-04-04 22:16:29 +00:00
if now := time . Now ( ) . Unix ( ) ; tstamp > now + 1 {
2015-06-29 16:55:49 +00:00
wait := time . Duration ( tstamp - now ) * time . Second
2017-04-04 22:16:29 +00:00
log . Info ( "Mining too far in the future" , "wait" , common . PrettyDuration ( wait ) )
2015-06-29 16:55:49 +00:00
time . Sleep ( wait )
}
2015-06-16 10:41:50 +00:00
num := parent . Number ( )
header := & types . Header {
ParentHash : parent . Hash ( ) ,
Number : num . Add ( num , common . Big1 ) ,
GasLimit : core . CalcGasLimit ( parent ) ,
Extra : self . extra ,
2015-08-24 00:52:53 +00:00
Time : big . NewInt ( tstamp ) ,
2015-06-16 10:41:50 +00:00
}
2018-08-03 08:33:37 +00:00
// Only set the coinbase if our consensus engine is running (avoid spurious block rewards)
if self . isRunning ( ) {
if self . coinbase == ( common . Address { } ) {
log . Error ( "Refusing to mine without etherbase" )
return
}
2017-04-04 22:16:29 +00:00
header . Coinbase = self . coinbase
}
if err := self . engine . Prepare ( self . chain , header ) ; err != nil {
log . Error ( "Failed to prepare header for mining" , "err" , err )
return
}
2016-07-08 15:48:17 +00:00
// If we are care about TheDAO hard-fork check whether to override the extra-data or not
2016-07-08 10:00:37 +00:00
if daoBlock := self . config . DAOForkBlock ; daoBlock != nil {
// Check whether the block is among the fork extra-override range
limit := new ( big . Int ) . Add ( daoBlock , params . DAOForkExtraRange )
2016-07-14 08:22:58 +00:00
if header . Number . Cmp ( daoBlock ) >= 0 && header . Number . Cmp ( limit ) < 0 {
2016-07-08 15:48:17 +00:00
// Depending whether we support or oppose the fork, override differently
if self . config . DAOForkSupport {
header . Extra = common . CopyBytes ( params . DAOForkBlockExtra )
2017-01-06 15:44:20 +00:00
} else if bytes . Equal ( header . Extra , params . DAOForkBlockExtra ) {
2016-07-08 15:48:17 +00:00
header . Extra = [ ] byte { } // If miner opposes, don't let it use the reserved extra-data
}
2016-07-08 10:00:37 +00:00
}
}
2015-10-06 14:35:55 +00:00
// Could potentially happen if starting to mine in an odd state.
err := self . makeCurrent ( parent , header )
if err != nil {
2017-04-04 22:16:29 +00:00
log . Error ( "Failed to create mining context" , "err" , err )
2015-10-06 14:35:55 +00:00
return
}
2016-07-11 10:55:11 +00:00
// Create the current work task and check any fork transitions needed
2015-08-04 18:38:57 +00:00
work := self . current
2016-07-11 10:55:11 +00:00
if self . config . DAOForkSupport && self . config . DAOForkBlock != nil && self . config . DAOForkBlock . Cmp ( header . Number ) == 0 {
2017-04-04 22:16:29 +00:00
misc . ApplyDAOHardFork ( work . state )
2016-07-11 10:55:11 +00:00
}
2016-06-27 15:28:34 +00:00
2015-06-16 10:41:50 +00:00
// compute uncles for the new block.
2015-03-23 17:27:05 +00:00
var (
uncles [ ] * types . Header
badUncles [ ] common . Hash
)
2015-03-23 11:12:49 +00:00
for hash , uncle := range self . possibleUncles {
2015-03-23 15:14:33 +00:00
if len ( uncles ) == 2 {
2015-03-23 11:12:49 +00:00
break
}
2015-08-04 18:38:57 +00:00
if err := self . commitUncle ( work , uncle . Header ( ) ) ; err != nil {
2017-04-04 22:16:29 +00:00
log . Trace ( "Bad uncle found and will be removed" , "hash" , hash )
2017-02-22 12:10:07 +00:00
log . Trace ( fmt . Sprint ( uncle ) )
2015-03-23 17:27:05 +00:00
badUncles = append ( badUncles , hash )
2015-03-23 11:12:49 +00:00
} else {
2017-04-04 22:16:29 +00:00
log . Debug ( "Committing new uncle to block" , "hash" , hash )
2015-03-23 15:14:33 +00:00
uncles = append ( uncles , uncle . Header ( ) )
2015-03-23 11:12:49 +00:00
}
}
2015-03-23 17:27:05 +00:00
for _ , hash := range badUncles {
delete ( self . possibleUncles , hash )
}
2018-08-03 08:33:37 +00:00
// Create an empty block based on temporary copied state for sealing in advance without waiting block
// execution finished.
if work . Block , err = self . engine . Finalize ( self . chain , header , work . state . Copy ( ) , nil , uncles , nil ) ; err != nil {
log . Error ( "Failed to finalize block for temporary sealing" , "err" , err )
} else {
// Push empty work in advance without applying pending transaction.
// The reason is transactions execution can cost a lot and sealer need to
// take advantage of this part time.
if self . isRunning ( ) {
log . Info ( "Commit new empty mining work" , "number" , work . Block . Number ( ) , "uncles" , len ( uncles ) )
self . push ( work )
}
}
// Fill the block with all available pending transactions.
pending , err := self . eth . TxPool ( ) . Pending ( )
if err != nil {
log . Error ( "Failed to fetch pending transactions" , "err" , err )
return
}
txs := types . NewTransactionsByPriceAndNonce ( self . current . signer , pending )
work . commitTransactions ( self . mux , txs , self . chain , self . coinbase )
// Create the full block to seal with the consensus engine
2017-04-04 22:16:29 +00:00
if work . Block , err = self . engine . Finalize ( self . chain , header , work . state , work . txs , uncles , work . receipts ) ; err != nil {
log . Error ( "Failed to finalize block for sealing" , "err" , err )
return
2015-06-29 13:17:05 +00:00
}
2015-06-16 10:41:50 +00:00
// We only care about logging if we're actually mining.
2018-08-03 08:33:37 +00:00
if self . isRunning ( ) {
log . Info ( "Commit new full mining work" , "number" , work . Block . Number ( ) , "txs" , work . tcount , "uncles" , len ( uncles ) , "elapsed" , common . PrettyDuration ( time . Since ( tstart ) ) )
2016-12-13 13:10:52 +00:00
self . unconfirmed . Shift ( work . Block . NumberU64 ( ) - 1 )
2018-08-03 08:33:37 +00:00
self . push ( work )
2015-06-16 10:41:50 +00:00
}
2018-04-16 07:56:20 +00:00
self . updateSnapshot ( )
2015-02-04 13:52:59 +00:00
}
2015-08-04 18:38:57 +00:00
func ( self * worker ) commitUncle ( work * Work , uncle * types . Header ) error {
2015-06-16 10:41:50 +00:00
hash := uncle . Hash ( )
2018-07-16 07:54:19 +00:00
if work . uncles . Contains ( hash ) {
2017-04-06 11:58:03 +00:00
return fmt . Errorf ( "uncle not unique" )
2015-02-04 13:52:59 +00:00
}
2018-07-16 07:54:19 +00:00
if ! work . ancestors . Contains ( uncle . ParentHash ) {
2017-04-06 11:58:03 +00:00
return fmt . Errorf ( "uncle's parent unknown (%x)" , uncle . ParentHash [ 0 : 4 ] )
2015-02-04 13:52:59 +00:00
}
2018-07-16 07:54:19 +00:00
if work . family . Contains ( hash ) {
2017-04-06 11:58:03 +00:00
return fmt . Errorf ( "uncle already in family (%x)" , hash )
2015-02-04 13:52:59 +00:00
}
2015-08-04 18:38:57 +00:00
work . uncles . Add ( uncle . Hash ( ) )
2015-02-04 13:52:59 +00:00
return nil
}
2018-04-16 07:56:20 +00:00
func ( self * worker ) updateSnapshot ( ) {
self . snapshotMu . Lock ( )
defer self . snapshotMu . Unlock ( )
2018-08-03 08:33:37 +00:00
var uncles [ ] * types . Header
self . current . uncles . Each ( func ( item interface { } ) bool {
if header , ok := item . ( * types . Header ) ; ok {
uncles = append ( uncles , header )
return true
}
return false
} )
2018-04-16 07:56:20 +00:00
self . snapshotBlock = types . NewBlock (
self . current . header ,
self . current . txs ,
2018-08-03 08:33:37 +00:00
uncles ,
2018-04-16 07:56:20 +00:00
self . current . receipts ,
)
self . snapshotState = self . current . state . Copy ( )
}
2017-05-16 19:07:27 +00:00
func ( env * Work ) commitTransactions ( mux * event . TypeMux , txs * types . TransactionsByPriceAndNonce , bc * core . BlockChain , coinbase common . Address ) {
2018-05-10 07:04:45 +00:00
if env . gasPool == nil {
env . gasPool = new ( core . GasPool ) . AddGas ( env . header . GasLimit )
}
2016-02-13 00:40:44 +00:00
2017-01-05 13:03:50 +00:00
var coalescedLogs [ ] * types . Log
2016-09-08 08:44:18 +00:00
2016-08-09 11:54:36 +00:00
for {
2018-01-15 10:57:06 +00:00
// If we don't have enough gas for any further transactions then we're done
2018-05-10 07:04:45 +00:00
if env . gasPool . Gas ( ) < params . TxGas {
2018-05-18 08:45:52 +00:00
log . Trace ( "Not enough gas for further transactions" , "have" , env . gasPool , "want" , params . TxGas )
2018-01-15 10:57:06 +00:00
break
}
2016-08-09 11:54:36 +00:00
// Retrieve the next transaction and abort if all done
tx := txs . Peek ( )
if tx == nil {
break
}
2016-01-19 22:50:00 +00:00
// Error may be ignored here. The error has already been checked
// during transaction acceptance is the transaction pool.
2016-11-02 12:44:13 +00:00
//
// We use the eip155 signer regardless of the current hf.
from , _ := types . Sender ( env . signer , tx )
// Check whether the tx is replay protected. If we're not in the EIP155 hf
// phase, start ignoring the sender until we do.
if tx . Protected ( ) && ! env . config . IsEIP155 ( env . header . Number ) {
2017-04-04 22:16:29 +00:00
log . Trace ( "Ignoring reply protected transaction" , "hash" , tx . Hash ( ) , "eip155" , env . config . EIP155Block )
2016-11-02 12:44:13 +00:00
txs . Pop ( )
continue
}
2016-08-09 11:54:36 +00:00
// Start executing the transaction
2017-02-01 21:36:51 +00:00
env . state . Prepare ( tx . Hash ( ) , common . Hash { } , env . tcount )
2015-05-10 23:28:15 +00:00
2018-05-10 07:04:45 +00:00
err , logs := env . commitTransaction ( tx , bc , coinbase , env . gasPool )
2017-04-06 11:58:03 +00:00
switch err {
case core . ErrGasLimitReached :
2016-08-09 11:54:36 +00:00
// Pop the current out-of-gas transaction without shifting in the next from the account
2017-04-04 22:16:29 +00:00
log . Trace ( "Gas limit exceeded for current block" , "sender" , from )
2016-08-09 11:54:36 +00:00
txs . Pop ( )
2015-07-06 09:54:11 +00:00
2017-09-04 19:35:00 +00:00
case core . ErrNonceTooLow :
// New head notification data race between the transaction pool and miner, shift
log . Trace ( "Skipping transaction with low nonce" , "sender" , from , "nonce" , tx . Nonce ( ) )
txs . Shift ( )
case core . ErrNonceTooHigh :
// Reorg notification data race between the transaction pool and miner, skip account =
log . Trace ( "Skipping account with hight nonce" , "sender" , from , "nonce" , tx . Nonce ( ) )
txs . Pop ( )
2017-04-06 11:58:03 +00:00
case nil :
2016-08-09 11:54:36 +00:00
// Everything ok, collect the logs and shift in the next transaction from the same account
2016-02-13 00:40:44 +00:00
coalescedLogs = append ( coalescedLogs , logs ... )
2016-08-09 11:54:36 +00:00
env . tcount ++
txs . Shift ( )
2017-04-06 11:58:03 +00:00
default :
2017-09-04 19:35:00 +00:00
// Strange error, discard the transaction and get the next in line (note, the
// nonce-too-high clause will prevent us from executing in vain).
log . Debug ( "Transaction failed, account skipped" , "hash" , tx . Hash ( ) , "err" , err )
txs . Shift ( )
2015-05-10 23:28:15 +00:00
}
}
2016-11-28 13:59:06 +00:00
2016-02-26 16:48:39 +00:00
if len ( coalescedLogs ) > 0 || env . tcount > 0 {
2016-11-28 13:59:06 +00:00
// make a copy, the state caches the logs and these logs get "upgraded" from pending to mined
// logs by filling in the block hash when the block was mined by the local miner. This can
// cause a race condition if a log was "upgraded" before the PendingLogsEvent is processed.
2017-01-05 13:03:50 +00:00
cpy := make ( [ ] * types . Log , len ( coalescedLogs ) )
2016-11-28 13:59:06 +00:00
for i , l := range coalescedLogs {
2017-01-05 13:03:50 +00:00
cpy [ i ] = new ( types . Log )
2016-11-28 13:59:06 +00:00
* cpy [ i ] = * l
}
2017-01-05 13:03:50 +00:00
go func ( logs [ ] * types . Log , tcount int ) {
2016-02-26 16:48:39 +00:00
if len ( logs ) > 0 {
mux . Post ( core . PendingLogsEvent { Logs : logs } )
}
if tcount > 0 {
mux . Post ( core . PendingStateEvent { } )
}
2016-11-28 13:59:06 +00:00
} ( cpy , env . tcount )
2016-02-13 00:40:44 +00:00
}
2015-05-10 23:28:15 +00:00
}
2017-04-12 13:38:31 +00:00
func ( env * Work ) commitTransaction ( tx * types . Transaction , bc * core . BlockChain , coinbase common . Address , gp * core . GasPool ) ( error , [ ] * types . Log ) {
2016-10-04 10:36:02 +00:00
snap := env . state . Snapshot ( )
2016-03-24 12:06:10 +00:00
2017-11-13 11:47:27 +00:00
receipt , _ , err := core . ApplyTransaction ( env . config , bc , & coinbase , gp , env . state , env . header , tx , & env . header . GasUsed , vm . Config { } )
2015-07-06 09:54:11 +00:00
if err != nil {
2016-10-04 10:36:02 +00:00
env . state . RevertToSnapshot ( snap )
2016-02-13 00:40:44 +00:00
return err , nil
2015-02-04 13:52:59 +00:00
}
2015-06-16 10:41:50 +00:00
env . txs = append ( env . txs , tx )
env . receipts = append ( env . receipts , receipt )
2016-02-13 00:40:44 +00:00
2017-01-05 10:52:10 +00:00
return nil , receipt . Logs
2015-02-04 13:52:59 +00:00
}