2015-07-06 17:54:22 -07:00
// Copyright 2015 The go-ethereum Authors
2015-07-22 09:48:40 -07:00
// This file is part of the go-ethereum library.
2015-07-06 17:54:22 -07:00
//
2015-07-23 09:35:11 -07:00
// The go-ethereum library is free software: you can redistribute it and/or modify
2015-07-06 17:54:22 -07: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 09:48:40 -07:00
// The go-ethereum library is distributed in the hope that it will be useful,
2015-07-06 17:54:22 -07:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
2015-07-22 09:48:40 -07:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-06 17:54:22 -07: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 09:48:40 -07:00
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
2015-07-06 17:54:22 -07:00
2015-02-04 05:52:59 -08:00
package miner
import (
2016-07-08 08:48:17 -07:00
"bytes"
2015-02-04 05:52:59 -08:00
"fmt"
"math/big"
2015-02-15 07:16:27 -08:00
"sync"
2015-03-26 09:45:03 -07:00
"sync/atomic"
2015-06-15 02:33:08 -07:00
"time"
2015-02-04 05:52:59 -08:00
2015-05-10 14:12:18 -07:00
"github.com/ethereum/go-ethereum/accounts"
2015-03-18 05:00:01 -07:00
"github.com/ethereum/go-ethereum/common"
2015-02-04 05:52:59 -08:00
"github.com/ethereum/go-ethereum/core"
2015-03-23 10:27:05 -07:00
"github.com/ethereum/go-ethereum/core/state"
2015-02-04 05:52:59 -08:00
"github.com/ethereum/go-ethereum/core/types"
2015-08-30 01:19:10 -07:00
"github.com/ethereum/go-ethereum/core/vm"
2015-09-14 00:35:57 -07:00
"github.com/ethereum/go-ethereum/ethdb"
2015-02-04 05:52:59 -08:00
"github.com/ethereum/go-ethereum/event"
2017-02-22 04:10:07 -08:00
"github.com/ethereum/go-ethereum/log"
2016-07-08 03:00:37 -07:00
"github.com/ethereum/go-ethereum/params"
2015-02-04 05:52:59 -08:00
"github.com/ethereum/go-ethereum/pow"
"gopkg.in/fatih/set.v0"
)
2015-07-11 11:45:59 -07:00
const (
resultQueueSize = 10
miningLogAtDepth = 5
)
2015-05-11 12:47:34 -07:00
// Agent can register themself with the worker
type Agent interface {
2015-07-11 11:45:59 -07:00
Work ( ) chan <- * Work
SetReturnCh ( chan <- * Result )
2015-05-11 12:47:34 -07:00
Stop ( )
Start ( )
GetHashRate ( ) int64
}
2016-08-15 11:14:05 -07:00
// Work is the workers current environment and holds
2015-05-11 12:47:34 -07:00
// all of the current state information
2015-07-11 11:45:59 -07:00
type Work struct {
2016-11-02 05:44:13 -07:00
config * params . ChainConfig
signer types . Signer
2016-12-13 03:23:12 -08:00
state * state . StateDB // apply state changes here
ancestors * set . Set // ancestor set (used for checking uncle parent validity)
family * set . Set // family set (used for checking uncle invalidity)
uncles * set . Set // uncle set
tcount int // tx count in cycle
ownedAccounts * set . Set
lowGasTxs types . Transactions
failedTxs types . Transactions
2015-02-04 05:52:59 -08:00
2015-07-11 11:45:59 -07:00
Block * types . Block // the new block
2015-02-04 05:52:59 -08:00
2015-06-16 03:41:50 -07:00
header * types . Header
txs [ ] * types . Transaction
receipts [ ] * types . Receipt
2015-07-11 11:45:59 -07:00
createdAt time . Time
}
type Result struct {
Work * Work
Block * types . Block
2015-02-04 05:52:59 -08:00
}
2015-05-11 12:47:34 -07:00
// worker is the main object which takes care of applying messages to the new state
2015-02-04 05:52:59 -08:00
type worker struct {
2016-10-20 04:36:29 -07:00
config * params . ChainConfig
2016-03-01 14:32:43 -08:00
2015-03-26 09:45:03 -07:00
mu sync . Mutex
2016-03-28 18:08:16 -07:00
// update loop
mux * event . TypeMux
2016-12-10 10:02:14 -08:00
events * event . TypeMuxSubscription
2016-03-28 18:08:16 -07:00
wg sync . WaitGroup
2015-10-29 05:28:00 -07:00
agents map [ Agent ] struct { }
2015-07-11 11:45:59 -07:00
recv chan * Result
2015-02-04 05:52:59 -08:00
pow pow . PoW
2016-08-15 11:14:05 -07:00
eth Backend
2015-08-31 08:09:50 -07:00
chain * core . BlockChain
2015-10-19 07:08:17 -07:00
proc core . Validator
2015-09-14 00:35:57 -07:00
chainDb ethdb . Database
2015-04-05 09:57:03 -07:00
2015-03-18 05:00:01 -07:00
coinbase common . Address
2015-05-09 03:04:00 -07:00
gasPrice * big . Int
2015-04-05 09:57:03 -07:00
extra [ ] byte
2015-02-04 05:52:59 -08:00
2015-04-07 03:32:55 -07:00
currentMu sync . Mutex
2015-07-11 11:45:59 -07:00
current * Work
2015-02-13 08:23:09 -08:00
2015-03-23 04:12:49 -07:00
uncleMu sync . Mutex
possibleUncles map [ common . Hash ] * types . Block
2015-04-07 03:32:55 -07:00
txQueueMu sync . Mutex
txQueue map [ common . Hash ] * types . Transaction
2016-12-13 05:10:52 -08:00
unconfirmed * unconfirmedBlocks // set of locally mined blocks pending canonicalness confirmations
2016-12-13 03:23:12 -08:00
2015-04-22 01:58:43 -07:00
// atomic status counters
mining int32
atWork int32
2015-07-11 11:45:59 -07:00
fullValidation bool
2015-02-04 05:52:59 -08:00
}
2016-10-20 04:36:29 -07:00
func newWorker ( config * params . ChainConfig , coinbase common . Address , eth Backend , mux * event . TypeMux ) * worker {
2015-04-07 03:32:55 -07:00
worker := & worker {
2016-03-01 14:32:43 -08:00
config : config ,
2015-03-23 04:12:49 -07:00
eth : eth ,
2016-08-15 11:14:05 -07:00
mux : mux ,
2015-08-06 10:57:39 -07:00
chainDb : eth . ChainDb ( ) ,
2015-07-11 11:45:59 -07:00
recv : make ( chan * Result , resultQueueSize ) ,
2015-05-09 03:04:00 -07:00
gasPrice : new ( big . Int ) ,
2015-08-31 08:09:50 -07:00
chain : eth . BlockChain ( ) ,
2015-10-19 07:08:17 -07:00
proc : eth . BlockChain ( ) . Validator ( ) ,
2015-03-23 04:12:49 -07:00
possibleUncles : make ( map [ common . Hash ] * types . Block ) ,
coinbase : coinbase ,
2015-04-07 03:32:55 -07:00
txQueue : make ( map [ common . Hash ] * types . Transaction ) ,
2015-10-29 05:28:00 -07:00
agents : make ( map [ Agent ] struct { } ) ,
2016-12-13 05:10:52 -08:00
unconfirmed : newUnconfirmedBlocks ( eth . BlockChain ( ) , 5 ) ,
2015-07-11 11:45:59 -07:00
fullValidation : false ,
2015-02-09 07:20:34 -08:00
}
2016-03-28 18:08:16 -07:00
worker . events = worker . mux . Subscribe ( core . ChainHeadEvent { } , core . ChainSideEvent { } , core . TxPreEvent { } )
2015-04-07 03:32:55 -07:00
go worker . update ( )
2016-03-28 18:08:16 -07:00
go worker . wait ( )
2015-04-07 03:32:55 -07:00
worker . commitNewWork ( )
return worker
2015-02-09 07:20:34 -08:00
}
2015-07-07 01:58:47 -07:00
func ( self * worker ) setEtherbase ( addr common . Address ) {
self . mu . Lock ( )
defer self . mu . Unlock ( )
self . coinbase = addr
}
2016-12-13 04:03:18 -08:00
func ( self * worker ) setExtra ( extra [ ] byte ) {
self . mu . Lock ( )
defer self . mu . Unlock ( )
self . extra = extra
}
2016-03-16 02:20:02 -07:00
func ( self * worker ) pending ( ) ( * types . Block , * state . StateDB ) {
2015-04-07 03:32:55 -07:00
self . currentMu . Lock ( )
defer self . currentMu . Unlock ( )
2015-07-20 04:37:43 -07:00
2015-06-16 03:41:50 -07:00
if atomic . LoadInt32 ( & self . mining ) == 0 {
return types . NewBlock (
self . current . header ,
self . current . txs ,
nil ,
self . current . receipts ,
2016-10-18 13:34:37 -07:00
) , self . current . state . Copy ( )
2015-06-16 03:41:50 -07:00
}
2016-10-04 03:36:02 -07:00
return self . current . Block , self . current . state . Copy ( )
2015-04-07 03:32:55 -07:00
}
2016-11-30 01:48:48 -08:00
func ( self * worker ) pendingBlock ( ) * types . Block {
self . currentMu . Lock ( )
defer self . currentMu . Unlock ( )
if atomic . LoadInt32 ( & self . mining ) == 0 {
return types . NewBlock (
self . current . header ,
self . current . txs ,
nil ,
self . current . receipts ,
)
}
return self . current . Block
}
2015-04-07 03:32:55 -07:00
func ( self * worker ) start ( ) {
2015-05-09 03:32:36 -07:00
self . mu . Lock ( )
defer self . mu . Unlock ( )
2015-05-10 16:28:15 -07:00
atomic . StoreInt32 ( & self . mining , 1 )
2015-02-14 07:52:14 -08:00
// spin up agents
2015-10-29 05:28:00 -07:00
for agent := range self . agents {
2015-02-14 07:52:14 -08:00
agent . Start ( )
}
2015-02-09 07:20:34 -08:00
}
func ( self * worker ) stop ( ) {
2016-03-28 18:08:16 -07:00
self . wg . Wait ( )
2015-05-09 03:32:36 -07:00
self . mu . Lock ( )
defer self . mu . Unlock ( )
2015-04-22 01:58:43 -07:00
if atomic . LoadInt32 ( & self . mining ) == 1 {
2015-10-29 05:28:00 -07:00
// Stop all agents.
for agent := range self . agents {
2015-04-07 15:30:23 -07:00
agent . Stop ( )
2015-10-29 05:28:00 -07:00
// Remove CPU agents.
if _ , ok := agent . ( * CpuAgent ) ; ok {
delete ( self . agents , agent )
2015-05-11 06:43:14 -07:00
}
2015-04-07 15:30:23 -07:00
}
}
2015-02-13 08:23:09 -08:00
2015-04-22 01:58:43 -07:00
atomic . StoreInt32 ( & self . mining , 0 )
atomic . StoreInt32 ( & self . atWork , 0 )
2015-02-09 07:20:34 -08:00
}
func ( self * worker ) register ( agent Agent ) {
2015-05-09 03:32:36 -07:00
self . mu . Lock ( )
defer self . mu . Unlock ( )
2015-10-29 05:28:00 -07:00
self . agents [ agent ] = struct { } { }
2015-03-24 02:34:06 -07:00
agent . SetReturnCh ( self . recv )
2015-02-04 05:52:59 -08:00
}
2015-10-29 05:28:00 -07:00
func ( self * worker ) unregister ( agent Agent ) {
self . mu . Lock ( )
defer self . mu . Unlock ( )
delete ( self . agents , agent )
agent . Stop ( )
}
2015-02-04 05:52:59 -08:00
func ( self * worker ) update ( ) {
2016-03-28 18:08:16 -07:00
for event := range self . events . Chan ( ) {
// A real event arrived, process interesting content
switch ev := event . Data . ( type ) {
case core . ChainHeadEvent :
self . commitNewWork ( )
case core . ChainSideEvent :
self . uncleMu . Lock ( )
self . possibleUncles [ ev . Block . Hash ( ) ] = ev . Block
self . uncleMu . Unlock ( )
case core . TxPreEvent :
// Apply transaction to the pending state if we're not mining
if atomic . LoadInt32 ( & self . mining ) == 0 {
self . currentMu . Lock ( )
2016-08-09 04:54:36 -07:00
2016-11-02 05:44:13 -07:00
acc , _ := types . Sender ( self . current . signer , ev . Tx )
2017-01-06 06:52:03 -08:00
txs := map [ common . Address ] types . Transactions { acc : { ev . Tx } }
2016-08-09 04:54:36 -07:00
txset := types . NewTransactionsByPriceAndNonce ( txs )
self . current . commitTransactions ( self . mux , txset , self . gasPrice , self . chain )
2016-03-28 18:08:16 -07:00
self . currentMu . Unlock ( )
2015-02-04 05:52:59 -08:00
}
}
}
}
2015-02-09 07:20:34 -08:00
func ( self * worker ) wait ( ) {
for {
2016-11-28 05:59:06 -08:00
mustCommitNewWork := true
2015-07-11 11:45:59 -07:00
for result := range self . recv {
2015-04-22 01:58:43 -07:00
atomic . AddInt32 ( & self . atWork , - 1 )
2015-03-26 09:45:03 -07:00
2015-07-11 11:45:59 -07:00
if result == nil {
2015-03-26 09:45:03 -07:00
continue
}
2015-07-11 11:45:59 -07:00
block := result . Block
2015-08-04 11:38:57 -07:00
work := result . Work
2015-03-26 09:45:03 -07:00
2015-07-11 11:45:59 -07:00
if self . fullValidation {
if _ , err := self . chain . InsertChain ( types . Blocks { block } ) ; err != nil {
2017-02-22 04:10:07 -08:00
log . Error ( fmt . Sprint ( "mining err" , err ) )
2015-07-11 11:45:59 -07:00
continue
}
2016-04-15 02:06:57 -07:00
go self . mux . Post ( core . NewMinedBlockEvent { Block : block } )
2015-07-11 11:45:59 -07:00
} else {
2016-10-20 04:36:29 -07:00
work . state . Commit ( self . config . IsEIP158 ( block . Number ( ) ) )
2016-04-05 06:22:04 -07:00
parent := self . chain . GetBlock ( block . ParentHash ( ) , block . NumberU64 ( ) - 1 )
2015-07-11 11:45:59 -07:00
if parent == nil {
2017-02-22 04:10:07 -08:00
log . Error ( fmt . Sprint ( "Invalid block found during mining" ) )
2015-07-11 11:45:59 -07:00
continue
}
2015-10-19 07:08:17 -07:00
auxValidator := self . eth . BlockChain ( ) . AuxValidator ( )
2016-03-01 14:32:43 -08:00
if err := core . ValidateHeader ( self . config , auxValidator , block . Header ( ) , parent . Header ( ) , true , false ) ; err != nil && err != core . BlockFutureErr {
2017-02-22 04:10:07 -08:00
log . Error ( fmt . Sprint ( "Invalid header on mined block:" , err ) )
2015-07-11 11:45:59 -07:00
continue
}
2015-07-03 02:24:42 -07:00
2015-09-07 10:43:01 -07:00
stat , err := self . chain . WriteBlock ( block )
2015-07-11 11:45:59 -07:00
if err != nil {
2017-02-22 04:10:07 -08:00
log . Error ( fmt . Sprint ( "error writing block to chain" , err ) )
2015-07-11 11:45:59 -07:00
continue
}
2015-11-19 07:02:49 -08:00
// update block hash 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 ( )
}
}
for _ , log := range work . state . Logs ( ) {
log . BlockHash = block . Hash ( )
}
2015-07-11 11:45:59 -07:00
// check if canon block and write transactions
if stat == core . CanonStatTy {
// This puts transactions in a extra db for rpc
2015-10-22 05:43:21 -07:00
core . WriteTransactions ( self . chainDb , block )
2015-07-11 11:45:59 -07:00
// store the receipts
2015-10-22 05:43:21 -07:00
core . WriteReceipts ( self . chainDb , work . receipts )
2015-10-12 08:58:51 -07:00
// Write map map bloom filters
core . WriteMipmapBloom ( self . chainDb , block . NumberU64 ( ) , work . receipts )
2016-11-28 05:59:06 -08:00
// implicit by posting ChainHeadEvent
mustCommitNewWork = false
2015-07-11 11:45:59 -07:00
}
// broadcast before waiting for validation
2017-01-05 05:03:50 -08:00
go func ( block * types . Block , logs [ ] * types . Log , receipts [ ] * types . Receipt ) {
2016-04-15 02:06:57 -07:00
self . mux . Post ( core . NewMinedBlockEvent { Block : block } )
self . mux . Post ( core . ChainEvent { Block : block , Hash : block . Hash ( ) , Logs : logs } )
2015-10-15 07:07:19 -07:00
2015-07-11 11:45:59 -07:00
if stat == core . CanonStatTy {
2016-04-15 02:06:57 -07:00
self . mux . Post ( core . ChainHeadEvent { Block : block } )
2015-07-11 11:45:59 -07:00
self . mux . Post ( logs )
}
2016-04-05 06:22:04 -07:00
if err := core . WriteBlockReceipts ( self . chainDb , block . Hash ( ) , block . NumberU64 ( ) , receipts ) ; err != nil {
2017-02-22 04:10:07 -08:00
log . Warn ( fmt . Sprint ( "error writing block receipts:" , err ) )
2015-08-18 12:16:33 -07:00
}
} ( block , work . state . Logs ( ) , work . receipts )
2015-07-03 02:24:42 -07:00
}
2016-12-13 03:23:12 -08:00
// Insert the block into the set of pending ones to wait for confirmations
2016-12-13 05:10:52 -08:00
self . unconfirmed . Insert ( block . NumberU64 ( ) , block . Hash ( ) )
2015-06-29 03:12:30 -07:00
2016-11-28 05:59:06 -08:00
if mustCommitNewWork {
self . commitNewWork ( )
}
2015-02-09 07:20:34 -08:00
}
}
}
2016-04-04 03:18:34 -07:00
// push sends a new work task to currently live miner agents.
2015-08-04 11:38:57 -07:00
func ( self * worker ) push ( work * Work ) {
2016-04-04 03:18:34 -07:00
if atomic . LoadInt32 ( & self . mining ) != 1 {
return
}
for agent := range self . agents {
atomic . AddInt32 ( & self . atWork , 1 )
if ch := agent . Work ( ) ; ch != nil {
ch <- work
2015-02-13 08:23:09 -08:00
}
2015-02-04 05:52:59 -08:00
}
}
2015-06-16 03:41:50 -07:00
// makeCurrent creates a new environment for the current cycle.
2015-10-06 07:35:55 -07:00
func ( self * worker ) makeCurrent ( parent * types . Block , header * types . Header ) error {
2016-09-27 03:13:13 -07:00
state , err := self . chain . StateAt ( parent . Root ( ) )
2015-10-06 07:35:55 -07:00
if err != nil {
return err
}
2015-08-04 11:38:57 -07:00
work := & Work {
2016-03-01 14:32:43 -08:00
config : self . config ,
2016-11-02 05:44:13 -07:00
signer : types . NewEIP155Signer ( self . config . ChainId ) ,
2015-06-16 03:41:50 -07:00
state : state ,
ancestors : set . New ( ) ,
family : set . New ( ) ,
uncles : set . New ( ) ,
header : header ,
2015-07-11 11:45:59 -07:00
createdAt : time . Now ( ) ,
2015-04-04 04:27:17 -07:00
}
2015-03-05 00:14:58 -08:00
2015-05-18 07:31:26 -07:00
// when 08 is processed ancestors contain 07 (quick block)
2015-06-16 03:41:50 -07:00
for _ , ancestor := range self . chain . GetBlocksFromHash ( parent . Hash ( ) , 7 ) {
2015-05-13 17:46:23 -07:00
for _ , uncle := range ancestor . Uncles ( ) {
2015-08-04 11:38:57 -07:00
work . family . Add ( uncle . Hash ( ) )
2015-05-13 17:46:23 -07:00
}
2015-08-04 11:38:57 -07:00
work . family . Add ( ancestor . Hash ( ) )
work . ancestors . Add ( ancestor . Hash ( ) )
2015-03-23 04:12:49 -07:00
}
2017-02-07 02:47:34 -08:00
wallets := self . eth . AccountManager ( ) . Wallets ( )
accounts := make ( [ ] accounts . Account , 0 , len ( wallets ) )
for _ , wallet := range wallets {
accounts = append ( accounts , wallet . Accounts ( ) ... )
}
2015-05-10 16:28:15 -07:00
// Keep track of transactions which return errors so they can be removed
2015-08-04 11:38:57 -07:00
work . tcount = 0
work . ownedAccounts = accountAddressesSet ( accounts )
self . current = work
2015-10-06 07:35:55 -07:00
return nil
2015-04-07 03:32:55 -07:00
}
2015-05-09 03:04:00 -07:00
func ( w * worker ) setGasPrice ( p * big . Int ) {
w . mu . Lock ( )
defer w . mu . Unlock ( )
2015-05-10 14:12:18 -07:00
// calculate the minimal gas price the miner accepts when sorting out transactions.
const pct = int64 ( 90 )
w . gasPrice = gasprice ( p , pct )
2016-04-15 02:06:57 -07:00
w . mux . Post ( core . GasPriceChanged { Price : w . gasPrice } )
2015-05-09 03:04:00 -07:00
}
2015-04-07 03:32:55 -07: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 02:33:08 -07:00
tstart := time . Now ( )
2015-06-16 03:41:50 -07:00
parent := self . chain . CurrentBlock ( )
2016-11-28 05:59:06 -08:00
2015-06-16 03:41:50 -07:00
tstamp := tstart . Unix ( )
2015-09-02 14:24:17 -07:00
if parent . Time ( ) . Cmp ( new ( big . Int ) . SetInt64 ( tstamp ) ) >= 0 {
2015-08-23 17:52:53 -07:00
tstamp = parent . Time ( ) . Int64 ( ) + 1
2015-06-16 03:41:50 -07:00
}
2015-06-29 09:55:49 -07:00
// this will ensure we're not going off too far in the future
if now := time . Now ( ) . Unix ( ) ; tstamp > now + 4 {
wait := time . Duration ( tstamp - now ) * time . Second
2017-02-22 04:10:07 -08:00
log . Info ( fmt . Sprint ( "We are too far in the future. Waiting for" , wait ) )
2015-06-29 09:55:49 -07:00
time . Sleep ( wait )
}
2015-06-16 03:41:50 -07:00
num := parent . Number ( )
header := & types . Header {
ParentHash : parent . Hash ( ) ,
Number : num . Add ( num , common . Big1 ) ,
2016-03-01 14:32:43 -08:00
Difficulty : core . CalcDifficulty ( self . config , uint64 ( tstamp ) , parent . Time ( ) . Uint64 ( ) , parent . Number ( ) , parent . Difficulty ( ) ) ,
2015-06-16 03:41:50 -07:00
GasLimit : core . CalcGasLimit ( parent ) ,
GasUsed : new ( big . Int ) ,
Coinbase : self . coinbase ,
Extra : self . extra ,
2015-08-23 17:52:53 -07:00
Time : big . NewInt ( tstamp ) ,
2015-06-16 03:41:50 -07:00
}
2016-07-08 08:48:17 -07:00
// If we are care about TheDAO hard-fork check whether to override the extra-data or not
2016-07-08 03:00:37 -07: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 01:22:58 -07:00
if header . Number . Cmp ( daoBlock ) >= 0 && header . Number . Cmp ( limit ) < 0 {
2016-07-08 08:48:17 -07:00
// Depending whether we support or oppose the fork, override differently
if self . config . DAOForkSupport {
header . Extra = common . CopyBytes ( params . DAOForkBlockExtra )
2017-01-06 07:44:20 -08:00
} else if bytes . Equal ( header . Extra , params . DAOForkBlockExtra ) {
2016-07-08 08:48:17 -07:00
header . Extra = [ ] byte { } // If miner opposes, don't let it use the reserved extra-data
}
2016-07-08 03:00:37 -07:00
}
}
2015-10-06 07:35:55 -07:00
// Could potentially happen if starting to mine in an odd state.
err := self . makeCurrent ( parent , header )
if err != nil {
2017-02-22 04:10:07 -08:00
log . Info ( fmt . Sprint ( "Could not create new env for mining, retrying on next block." ) )
2015-10-06 07:35:55 -07:00
return
}
2016-07-11 03:55:11 -07:00
// Create the current work task and check any fork transitions needed
2015-08-04 11:38:57 -07:00
work := self . current
2016-07-11 03:55:11 -07:00
if self . config . DAOForkSupport && self . config . DAOForkBlock != nil && self . config . DAOForkBlock . Cmp ( header . Number ) == 0 {
core . ApplyDAOHardFork ( work . state )
}
2016-12-10 14:54:58 -08:00
pending , err := self . eth . TxPool ( ) . Pending ( )
if err != nil {
2017-02-22 04:10:07 -08:00
log . Error ( fmt . Sprintf ( "Could not fetch pending transactions: %v" , err ) )
2016-12-10 14:54:58 -08:00
return
}
txs := types . NewTransactionsByPriceAndNonce ( pending )
2016-08-09 04:54:36 -07:00
work . commitTransactions ( self . mux , txs , self . gasPrice , self . chain )
2016-06-27 08:28:34 -07:00
2016-07-01 08:59:55 -07:00
self . eth . TxPool ( ) . RemoveBatch ( work . lowGasTxs )
self . eth . TxPool ( ) . RemoveBatch ( work . failedTxs )
2015-02-04 05:52:59 -08:00
2015-06-16 03:41:50 -07:00
// compute uncles for the new block.
2015-03-23 10:27:05 -07:00
var (
uncles [ ] * types . Header
badUncles [ ] common . Hash
)
2015-03-23 04:12:49 -07:00
for hash , uncle := range self . possibleUncles {
2015-03-23 08:14:33 -07:00
if len ( uncles ) == 2 {
2015-03-23 04:12:49 -07:00
break
}
2015-08-04 11:38:57 -07:00
if err := self . commitUncle ( work , uncle . Header ( ) ) ; err != nil {
2017-02-22 04:10:07 -08:00
log . Trace ( fmt . Sprintf ( "Bad uncle found and will be removed (%x)\n" , hash [ : 4 ] ) )
log . Trace ( fmt . Sprint ( uncle ) )
2015-03-23 10:27:05 -07:00
badUncles = append ( badUncles , hash )
2015-03-23 04:12:49 -07:00
} else {
2017-02-22 04:10:07 -08:00
log . Debug ( fmt . Sprintf ( "committing %x as uncle\n" , hash [ : 4 ] ) )
2015-03-23 08:14:33 -07:00
uncles = append ( uncles , uncle . Header ( ) )
2015-03-23 04:12:49 -07:00
}
}
2015-03-23 10:27:05 -07:00
for _ , hash := range badUncles {
delete ( self . possibleUncles , hash )
}
2015-03-23 08:35:44 -07:00
2015-06-29 06:17:05 -07:00
if atomic . LoadInt32 ( & self . mining ) == 1 {
// commit state root after all state transitions.
2015-08-04 11:38:57 -07:00
core . AccumulateRewards ( work . state , header , uncles )
2016-10-20 04:36:29 -07:00
header . Root = work . state . IntermediateRoot ( self . config . IsEIP158 ( header . Number ) )
2015-06-29 06:17:05 -07:00
}
2015-03-23 04:12:49 -07:00
2015-06-16 03:41:50 -07:00
// create the new block whose nonce will be mined.
2015-08-04 11:38:57 -07:00
work . Block = types . NewBlock ( header , work . txs , uncles , work . receipts )
2015-02-04 05:52:59 -08:00
2015-06-16 03:41:50 -07:00
// We only care about logging if we're actually mining.
if atomic . LoadInt32 ( & self . mining ) == 1 {
2017-02-22 04:10:07 -08:00
log . Info ( fmt . Sprintf ( "commit new work on block %v with %d txs & %d uncles. Took %v\n" , work . Block . Number ( ) , work . tcount , len ( uncles ) , time . Since ( tstart ) ) )
2016-12-13 05:10:52 -08:00
self . unconfirmed . Shift ( work . Block . NumberU64 ( ) - 1 )
2015-06-16 03:41:50 -07:00
}
2015-08-04 11:38:57 -07:00
self . push ( work )
2015-02-04 05:52:59 -08:00
}
2015-08-04 11:38:57 -07:00
func ( self * worker ) commitUncle ( work * Work , uncle * types . Header ) error {
2015-06-16 03:41:50 -07:00
hash := uncle . Hash ( )
2015-08-04 11:38:57 -07:00
if work . uncles . Has ( hash ) {
2015-02-04 05:52:59 -08:00
return core . UncleError ( "Uncle not unique" )
}
2015-08-04 11:38:57 -07:00
if ! work . ancestors . Has ( uncle . ParentHash ) {
2015-02-04 05:52:59 -08:00
return core . UncleError ( fmt . Sprintf ( "Uncle's parent unknown (%x)" , uncle . ParentHash [ 0 : 4 ] ) )
}
2015-08-04 11:38:57 -07:00
if work . family . Has ( hash ) {
2015-06-16 03:41:50 -07:00
return core . UncleError ( fmt . Sprintf ( "Uncle already in family (%x)" , hash ) )
2015-02-04 05:52:59 -08:00
}
2015-08-04 11:38:57 -07:00
work . uncles . Add ( uncle . Hash ( ) )
2015-02-04 05:52:59 -08:00
return nil
}
2016-08-09 04:54:36 -07:00
func ( env * Work ) commitTransactions ( mux * event . TypeMux , txs * types . TransactionsByPriceAndNonce , gasPrice * big . Int , bc * core . BlockChain ) {
2015-09-02 03:55:11 -07:00
gp := new ( core . GasPool ) . AddGas ( env . header . GasLimit )
2016-02-12 16:40:44 -08:00
2017-01-05 05:03:50 -08:00
var coalescedLogs [ ] * types . Log
2016-09-08 01:44:18 -07:00
2016-08-09 04:54:36 -07:00
for {
// Retrieve the next transaction and abort if all done
tx := txs . Peek ( )
if tx == nil {
break
}
2016-01-19 14:50:00 -08:00
// Error may be ignored here. The error has already been checked
// during transaction acceptance is the transaction pool.
2016-11-02 05:44:13 -07: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-02-22 04:10:07 -08:00
log . Trace ( fmt . Sprintf ( "Transaction (%x) is replay protected, but we haven't yet hardforked. Transaction will be ignored until we hardfork.\n" , tx . Hash ( ) ) )
2016-11-02 05:44:13 -07:00
txs . Pop ( )
continue
}
2015-05-10 16:28:15 -07:00
2016-08-09 04:54:36 -07:00
// Ignore any transactions (and accounts subsequently) with low gas limits
2015-06-16 03:41:50 -07:00
if tx . GasPrice ( ) . Cmp ( gasPrice ) < 0 && ! env . ownedAccounts . Has ( from ) {
2016-08-09 04:54:36 -07:00
// Pop the current low-priced transaction without shifting in the next from the account
2017-02-22 04:10:07 -08:00
log . Info ( fmt . Sprintf ( "Transaction (%x) below gas price (tx=%v ask=%v). All sequential txs from this address(%x) will be ignored\n" , tx . Hash ( ) . Bytes ( ) [ : 4 ] , common . CurrencyToString ( tx . GasPrice ( ) ) , common . CurrencyToString ( gasPrice ) , from [ : 4 ] ) )
2015-05-10 16:28:15 -07:00
2016-08-09 04:54:36 -07:00
env . lowGasTxs = append ( env . lowGasTxs , tx )
txs . Pop ( )
2015-05-10 16:28:15 -07:00
continue
}
2016-08-09 04:54:36 -07:00
// Start executing the transaction
2016-09-08 01:44:18 -07:00
env . state . StartRecord ( tx . Hash ( ) , common . Hash { } , env . tcount )
2015-05-10 16:28:15 -07:00
2016-02-12 16:40:44 -08:00
err , logs := env . commitTransaction ( tx , bc , gp )
2015-05-10 16:28:15 -07:00
switch {
2015-09-02 03:55:11 -07:00
case core . IsGasLimitErr ( err ) :
2016-08-09 04:54:36 -07:00
// Pop the current out-of-gas transaction without shifting in the next from the account
2017-02-22 04:10:07 -08:00
log . Trace ( fmt . Sprintf ( "Gas limit reached for (%x) in this block. Continue to try smaller txs\n" , from [ : 4 ] ) )
2016-08-09 04:54:36 -07:00
txs . Pop ( )
2015-07-06 02:54:11 -07:00
2016-06-27 08:28:34 -07:00
case err != nil :
2016-08-09 04:54:36 -07:00
// Pop the current failed transaction without shifting in the next from the account
2017-02-22 04:10:07 -08:00
log . Trace ( fmt . Sprintf ( "Transaction (%x) failed, will be removed: %v\n" , tx . Hash ( ) . Bytes ( ) [ : 4 ] , err ) )
2016-06-27 08:28:34 -07:00
env . failedTxs = append ( env . failedTxs , tx )
2016-08-09 04:54:36 -07:00
txs . Pop ( )
2015-05-10 16:28:15 -07:00
default :
2016-08-09 04:54:36 -07:00
// Everything ok, collect the logs and shift in the next transaction from the same account
2016-02-12 16:40:44 -08:00
coalescedLogs = append ( coalescedLogs , logs ... )
2016-08-09 04:54:36 -07:00
env . tcount ++
txs . Shift ( )
2015-05-10 16:28:15 -07:00
}
}
2016-11-28 05:59:06 -08:00
2016-02-26 08:48:39 -08:00
if len ( coalescedLogs ) > 0 || env . tcount > 0 {
2016-11-28 05:59:06 -08: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 05:03:50 -08:00
cpy := make ( [ ] * types . Log , len ( coalescedLogs ) )
2016-11-28 05:59:06 -08:00
for i , l := range coalescedLogs {
2017-01-05 05:03:50 -08:00
cpy [ i ] = new ( types . Log )
2016-11-28 05:59:06 -08:00
* cpy [ i ] = * l
}
2017-01-05 05:03:50 -08:00
go func ( logs [ ] * types . Log , tcount int ) {
2016-02-26 08:48:39 -08:00
if len ( logs ) > 0 {
mux . Post ( core . PendingLogsEvent { Logs : logs } )
}
if tcount > 0 {
mux . Post ( core . PendingStateEvent { } )
}
2016-11-28 05:59:06 -08:00
} ( cpy , env . tcount )
2016-02-12 16:40:44 -08:00
}
2015-05-10 16:28:15 -07:00
}
2017-01-05 05:03:50 -08:00
func ( env * Work ) commitTransaction ( tx * types . Transaction , bc * core . BlockChain , gp * core . GasPool ) ( error , [ ] * types . Log ) {
2016-10-04 03:36:02 -07:00
snap := env . state . Snapshot ( )
2016-03-24 05:06:10 -07:00
2017-01-05 02:52:10 -08:00
receipt , _ , err := core . ApplyTransaction ( env . config , bc , gp , env . state , env . header , tx , env . header . GasUsed , vm . Config { } )
2015-07-06 02:54:11 -07:00
if err != nil {
2016-10-04 03:36:02 -07:00
env . state . RevertToSnapshot ( snap )
2016-02-12 16:40:44 -08:00
return err , nil
2015-02-04 05:52:59 -08:00
}
2015-06-16 03:41:50 -07:00
env . txs = append ( env . txs , tx )
env . receipts = append ( env . receipts , receipt )
2016-02-12 16:40:44 -08:00
2017-01-05 02:52:10 -08:00
return nil , receipt . Logs
2015-02-04 05:52:59 -08:00
}
2015-02-28 14:09:49 -08:00
2015-05-13 18:39:07 -07:00
// TODO: remove or use
2015-02-28 14:09:49 -08:00
func ( self * worker ) HashRate ( ) int64 {
2015-05-13 18:39:07 -07:00
return 0
2015-02-28 14:09:49 -08:00
}
2015-05-09 03:13:46 -07:00
// gasprice calculates a reduced gas price based on the pct
// XXX Use big.Rat?
func gasprice ( price * big . Int , pct int64 ) * big . Int {
p := new ( big . Int ) . Set ( price )
p . Div ( p , big . NewInt ( 100 ) )
p . Mul ( p , big . NewInt ( pct ) )
return p
}
2015-05-10 14:12:18 -07:00
func accountAddressesSet ( accounts [ ] accounts . Account ) * set . Set {
accountSet := set . New ( )
for _ , account := range accounts {
2015-05-10 11:30:02 -07:00
accountSet . Add ( account . Address )
2015-05-10 14:12:18 -07:00
}
return accountSet
}