| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | package miner | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"sort" | 
					
						
							| 
									
										
										
										
											2015-02-15 16:16:27 +01:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2015-03-26 17:45:03 +01:00
										 |  |  | 	"sync/atomic" | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core" | 
					
						
							| 
									
										
										
										
											2015-03-23 18:27:05 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/state" | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/event" | 
					
						
							| 
									
										
										
										
											2015-03-01 16:09:59 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							| 
									
										
										
										
											2015-04-04 23:04:19 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	"github.com/ethereum/go-ethereum/pow" | 
					
						
							|  |  |  | 	"gopkg.in/fatih/set.v0" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-01 16:09:59 +01:00
										 |  |  | var jsonlogger = logger.NewJsonLogger() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | type environment struct { | 
					
						
							|  |  |  | 	totalUsedGas *big.Int | 
					
						
							|  |  |  | 	state        *state.StateDB | 
					
						
							|  |  |  | 	coinbase     *state.StateObject | 
					
						
							|  |  |  | 	block        *types.Block | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 	family       *set.Set | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	uncles       *set.Set | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 12:24:51 +01:00
										 |  |  | func env(block *types.Block, eth core.Backend) *environment { | 
					
						
							| 
									
										
										
										
											2015-03-06 18:26:16 +01:00
										 |  |  | 	state := state.New(block.Root(), eth.StateDb()) | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	env := &environment{ | 
					
						
							|  |  |  | 		totalUsedGas: new(big.Int), | 
					
						
							|  |  |  | 		state:        state, | 
					
						
							|  |  |  | 		block:        block, | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 		family:       set.New(), | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 		uncles:       set.New(), | 
					
						
							|  |  |  | 		coinbase:     state.GetOrNewStateObject(block.Coinbase()), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return env | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | type Work struct { | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	Number    uint64 | 
					
						
							| 
									
										
										
										
											2015-03-03 21:04:31 +01:00
										 |  |  | 	Nonce     uint64 | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	MixDigest []byte | 
					
						
							|  |  |  | 	SeedHash  []byte | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 15:05:47 -08:00
										 |  |  | type Agent interface { | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | 	Work() chan<- *types.Block | 
					
						
							| 
									
										
										
										
											2015-03-24 10:34:06 +01:00
										 |  |  | 	SetReturnCh(chan<- *types.Block) | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | 	Stop() | 
					
						
							| 
									
										
										
										
											2015-02-14 16:52:14 +01:00
										 |  |  | 	Start() | 
					
						
							| 
									
										
										
										
											2015-03-20 17:42:09 +01:00
										 |  |  | 	GetHashRate() int64 | 
					
						
							| 
									
										
										
										
											2015-02-04 15:05:47 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | type worker struct { | 
					
						
							| 
									
										
										
										
											2015-03-26 17:45:03 +01:00
										 |  |  | 	mu sync.Mutex | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | 	agents []Agent | 
					
						
							| 
									
										
										
										
											2015-03-24 10:34:06 +01:00
										 |  |  | 	recv   chan *types.Block | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	mux    *event.TypeMux | 
					
						
							|  |  |  | 	quit   chan struct{} | 
					
						
							|  |  |  | 	pow    pow.PoW | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-05 18:57:03 +02:00
										 |  |  | 	eth   core.Backend | 
					
						
							|  |  |  | 	chain *core.ChainManager | 
					
						
							|  |  |  | 	proc  *core.BlockProcessor | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | 	coinbase common.Address | 
					
						
							| 
									
										
										
										
											2015-04-05 18:57:03 +02:00
										 |  |  | 	extra    []byte | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 	currentMu sync.Mutex | 
					
						
							|  |  |  | 	current   *environment | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 	uncleMu        sync.Mutex | 
					
						
							|  |  |  | 	possibleUncles map[common.Hash]*types.Block | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 	txQueueMu sync.Mutex | 
					
						
							|  |  |  | 	txQueue   map[common.Hash]*types.Transaction | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 	// atomic status counters | 
					
						
							|  |  |  | 	mining int32 | 
					
						
							|  |  |  | 	atWork int32 | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | func newWorker(coinbase common.Address, eth core.Backend) *worker { | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 	worker := &worker{ | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 		eth:            eth, | 
					
						
							|  |  |  | 		mux:            eth.EventMux(), | 
					
						
							| 
									
										
										
										
											2015-03-24 10:34:06 +01:00
										 |  |  | 		recv:           make(chan *types.Block), | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 		chain:          eth.ChainManager(), | 
					
						
							|  |  |  | 		proc:           eth.BlockProcessor(), | 
					
						
							|  |  |  | 		possibleUncles: make(map[common.Hash]*types.Block), | 
					
						
							|  |  |  | 		coinbase:       coinbase, | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 		txQueue:        make(map[common.Hash]*types.Transaction), | 
					
						
							| 
									
										
										
										
											2015-04-08 00:30:23 +02:00
										 |  |  | 		quit:           make(chan struct{}), | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 	go worker.update() | 
					
						
							|  |  |  | 	go worker.wait() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	worker.commitNewWork() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return worker | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | func (self *worker) pendingState() *state.StateDB { | 
					
						
							|  |  |  | 	self.currentMu.Lock() | 
					
						
							|  |  |  | 	defer self.currentMu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return self.current.state | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | func (self *worker) pendingBlock() *types.Block { | 
					
						
							|  |  |  | 	self.currentMu.Lock() | 
					
						
							|  |  |  | 	defer self.currentMu.Unlock() | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 	return self.current.block | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *worker) start() { | 
					
						
							| 
									
										
										
										
											2015-02-14 16:52:14 +01:00
										 |  |  | 	// spin up agents | 
					
						
							|  |  |  | 	for _, agent := range self.agents { | 
					
						
							|  |  |  | 		agent.Start() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 	atomic.StoreInt32(&self.mining, 1) | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *worker) stop() { | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 	if atomic.LoadInt32(&self.mining) == 1 { | 
					
						
							| 
									
										
										
										
											2015-04-08 00:30:23 +02:00
										 |  |  | 		// stop all agents | 
					
						
							|  |  |  | 		for _, agent := range self.agents { | 
					
						
							|  |  |  | 			agent.Stop() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 	atomic.StoreInt32(&self.mining, 0) | 
					
						
							|  |  |  | 	atomic.StoreInt32(&self.atWork, 0) | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *worker) register(agent Agent) { | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	self.agents = append(self.agents, agent) | 
					
						
							| 
									
										
										
										
											2015-03-24 10:34:06 +01:00
										 |  |  | 	agent.SetReturnCh(self.recv) | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *worker) update() { | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 	events := self.mux.Subscribe(core.ChainHeadEvent{}, core.ChainSideEvent{}, core.TxPreEvent{}) | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case event := <-events.Chan(): | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 			switch ev := event.(type) { | 
					
						
							| 
									
										
										
										
											2015-03-06 15:50:44 +01:00
										 |  |  | 			case core.ChainHeadEvent: | 
					
						
							| 
									
										
										
										
											2015-02-14 16:52:14 +01:00
										 |  |  | 				self.commitNewWork() | 
					
						
							| 
									
										
										
										
											2015-03-23 16:14:33 +01:00
										 |  |  | 			case core.ChainSideEvent: | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 				self.uncleMu.Lock() | 
					
						
							|  |  |  | 				self.possibleUncles[ev.Block.Hash()] = ev.Block | 
					
						
							|  |  |  | 				self.uncleMu.Unlock() | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 			case core.TxPreEvent: | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 				if atomic.LoadInt32(&self.mining) == 0 { | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 					self.commitNewWork() | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case <-self.quit: | 
					
						
							|  |  |  | 			break out | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	events.Unsubscribe() | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | func (self *worker) wait() { | 
					
						
							|  |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2015-03-24 10:34:06 +01:00
										 |  |  | 		for block := range self.recv { | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 			atomic.AddInt32(&self.atWork, -1) | 
					
						
							| 
									
										
										
										
											2015-03-26 17:45:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if block == nil { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 14:00:24 +02:00
										 |  |  | 			if _, err := self.chain.InsertChain(types.Blocks{block}); err == nil { | 
					
						
							| 
									
										
										
										
											2015-03-24 10:34:06 +01:00
										 |  |  | 				for _, uncle := range block.Uncles() { | 
					
						
							|  |  |  | 					delete(self.possibleUncles, uncle.Hash()) | 
					
						
							| 
									
										
										
										
											2015-02-14 16:52:14 +01:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-03-24 10:34:06 +01:00
										 |  |  | 				self.mux.Post(core.NewMinedBlockEvent{block}) | 
					
						
							| 
									
										
										
										
											2015-03-25 13:51:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-17 15:00:37 +02:00
										 |  |  | 				glog.V(logger.Info).Infof("🔨  Mined block #%v", block.Number()) | 
					
						
							| 
									
										
										
										
											2015-04-02 12:58:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-25 13:51:12 +01:00
										 |  |  | 				jsonlogger.LogJson(&logger.EthMinerNewBlock{ | 
					
						
							|  |  |  | 					BlockHash:     block.Hash().Hex(), | 
					
						
							|  |  |  | 					BlockNumber:   block.Number(), | 
					
						
							|  |  |  | 					ChainHeadHash: block.ParentHeaderHash.Hex(), | 
					
						
							|  |  |  | 					BlockPrevHash: block.ParentHeaderHash.Hex(), | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2015-03-24 10:34:06 +01:00
										 |  |  | 			} else { | 
					
						
							|  |  |  | 				self.commitNewWork() | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *worker) push() { | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 	if atomic.LoadInt32(&self.mining) == 1 { | 
					
						
							| 
									
										
										
										
											2015-02-14 16:52:14 +01:00
										 |  |  | 		self.current.block.Header().GasUsed = self.current.totalUsedGas | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 		self.current.block.SetRoot(self.current.state.Root()) | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-14 16:52:14 +01:00
										 |  |  | 		// push new work to agents | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 		for _, agent := range self.agents { | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 			atomic.AddInt32(&self.atWork, 1) | 
					
						
							| 
									
										
										
										
											2015-03-26 17:45:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 17:04:22 +02:00
										 |  |  | 			if agent.Work() != nil { | 
					
						
							|  |  |  | 				agent.Work() <- self.current.block.Copy() | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				common.Report(fmt.Sprintf("%v %T\n", agent, agent)) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-02-13 17:23:09 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | func (self *worker) makeCurrent() { | 
					
						
							| 
									
										
										
										
											2015-03-05 09:14:58 +01:00
										 |  |  | 	block := self.chain.NewBlock(self.coinbase) | 
					
						
							| 
									
										
										
										
											2015-04-04 13:27:17 +02:00
										 |  |  | 	if block.Time() == self.chain.CurrentBlock().Time() { | 
					
						
							|  |  |  | 		block.Header().Time++ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-05 18:57:03 +02:00
										 |  |  | 	block.Header().Extra = self.extra | 
					
						
							| 
									
										
										
										
											2015-03-05 09:14:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	self.current = env(block, self.eth) | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 	for _, ancestor := range self.chain.GetAncestors(block, 7) { | 
					
						
							|  |  |  | 		self.current.family.Add(ancestor.Hash()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	parent := self.chain.GetBlock(self.current.block.ParentHash()) | 
					
						
							| 
									
										
										
										
											2015-04-26 11:19:40 +02:00
										 |  |  | 	self.current.coinbase.SetGasPool(core.CalcGasLimit(parent)) | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02: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() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	self.makeCurrent() | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	transactions := self.eth.TxPool().GetTransactions() | 
					
						
							|  |  |  | 	sort.Sort(types.TxByNonce{transactions}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Keep track of transactions which return errors so they can be removed | 
					
						
							| 
									
										
										
										
											2015-03-23 16:35:44 +01:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2015-04-21 11:26:04 +02:00
										 |  |  | 		remove             = set.New() | 
					
						
							|  |  |  | 		tcount             = 0 | 
					
						
							|  |  |  | 		ignoredTransactors = set.New() | 
					
						
							| 
									
										
										
										
											2015-03-23 16:35:44 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-04-21 22:03:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 22:58:53 +02:00
										 |  |  | 	for _, tx := range transactions { | 
					
						
							| 
									
										
										
										
											2015-04-21 11:26:04 +02:00
										 |  |  | 		// We can skip err. It has already been validated in the tx pool | 
					
						
							|  |  |  | 		from, _ := tx.From() | 
					
						
							|  |  |  | 		// Move on to the next transaction when the transactor is in ignored transactions set | 
					
						
							|  |  |  | 		// This may occur when a transaction hits the gas limit. When a gas limit is hit and | 
					
						
							|  |  |  | 		// the transaction is processed (that could potentially be included in the block) it | 
					
						
							|  |  |  | 		// will throw a nonce error because the previous transaction hasn't been processed. | 
					
						
							|  |  |  | 		// Therefor we need to ignore any transaction after the ignored one. | 
					
						
							|  |  |  | 		if ignoredTransactors.Has(from) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 17:14:58 +02:00
										 |  |  | 		self.current.state.StartRecord(tx.Hash(), common.Hash{}, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 		err := self.commitTransaction(tx) | 
					
						
							|  |  |  | 		switch { | 
					
						
							| 
									
										
										
										
											2015-04-08 00:30:23 +02:00
										 |  |  | 		case core.IsNonceErr(err) || core.IsInvalidTxErr(err): | 
					
						
							| 
									
										
										
										
											2015-02-15 16:16:27 +01:00
										 |  |  | 			// Remove invalid transactions | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | 			from, _ := tx.From() | 
					
						
							| 
									
										
										
										
											2015-04-21 11:26:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | 			self.chain.TxState().RemoveNonce(from, tx.Nonce()) | 
					
						
							| 
									
										
										
										
											2015-04-08 00:30:23 +02:00
										 |  |  | 			remove.Add(tx.Hash()) | 
					
						
							| 
									
										
										
										
											2015-04-04 23:04:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-13 22:58:53 +02:00
										 |  |  | 			if glog.V(logger.Detail) { | 
					
						
							| 
									
										
										
										
											2015-04-04 23:04:19 +02:00
										 |  |  | 				glog.Infof("TX (%x) failed, will be removed: %v\n", tx.Hash().Bytes()[:4], err) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-02-19 22:33:22 +01:00
										 |  |  | 		case state.IsGasLimitErr(err): | 
					
						
							| 
									
										
										
										
											2015-04-21 11:26:04 +02:00
										 |  |  | 			from, _ := tx.From() | 
					
						
							|  |  |  | 			// ignore the transactor so no nonce errors will be thrown for this account | 
					
						
							|  |  |  | 			// next time the worker is run, they'll be picked up again. | 
					
						
							|  |  |  | 			ignoredTransactors.Add(from) | 
					
						
							| 
									
										
										
										
											2015-04-23 10:53:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			glog.V(logger.Detail).Infof("Gas limit reached for (%x) in this block. Continue to try smaller txs\n", from[:4]) | 
					
						
							| 
									
										
										
										
											2015-03-23 16:35:44 +01:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			tcount++ | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 18:27:05 +01:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		uncles    []*types.Header | 
					
						
							|  |  |  | 		badUncles []common.Hash | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 	for hash, uncle := range self.possibleUncles { | 
					
						
							| 
									
										
										
										
											2015-03-23 16:14:33 +01:00
										 |  |  | 		if len(uncles) == 2 { | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if err := self.commitUncle(uncle.Header()); err != nil { | 
					
						
							| 
									
										
										
										
											2015-04-15 12:12:20 +02:00
										 |  |  | 			if glog.V(logger.Ridiculousness) { | 
					
						
							|  |  |  | 				glog.V(logger.Detail).Infof("Bad uncle found and will be removed (%x)\n", hash[:4]) | 
					
						
							|  |  |  | 				glog.V(logger.Detail).Infoln(uncle) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 18:27:05 +01:00
										 |  |  | 			badUncles = append(badUncles, hash) | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2015-04-07 14:57:04 +02:00
										 |  |  | 			glog.V(logger.Debug).Infof("commiting %x as uncle\n", hash[:4]) | 
					
						
							| 
									
										
										
										
											2015-03-23 16:14:33 +01:00
										 |  |  | 			uncles = append(uncles, uncle.Header()) | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-04-07 14:57:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// We only care about logging if we're actually mining | 
					
						
							| 
									
										
										
										
											2015-04-22 10:58:43 +02:00
										 |  |  | 	if atomic.LoadInt32(&self.mining) == 1 { | 
					
						
							| 
									
										
										
										
											2015-04-07 14:57:04 +02:00
										 |  |  | 		glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles\n", self.current.block.Number(), tcount, len(uncles)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 18:27:05 +01:00
										 |  |  | 	for _, hash := range badUncles { | 
					
						
							|  |  |  | 		delete(self.possibleUncles, hash) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-23 16:35:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 16:14:33 +01:00
										 |  |  | 	self.current.block.SetUncles(uncles) | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-01 21:18:41 +02:00
										 |  |  | 	core.AccumulateRewards(self.current.state, self.current.block) | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-01 23:58:26 +02:00
										 |  |  | 	self.current.state.Update() | 
					
						
							| 
									
										
										
										
											2015-04-07 12:32:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-09 16:20:34 +01:00
										 |  |  | 	self.push() | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	inclusionReward = new(big.Int).Div(core.BlockReward, big.NewInt(32)) | 
					
						
							|  |  |  | 	_uncleReward    = new(big.Int).Mul(core.BlockReward, big.NewInt(15)) | 
					
						
							|  |  |  | 	uncleReward     = new(big.Int).Div(_uncleReward, big.NewInt(16)) | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *worker) commitUncle(uncle *types.Header) error { | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | 	if self.current.uncles.Has(uncle.Hash()) { | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 		// Error not unique | 
					
						
							|  |  |  | 		return core.UncleError("Uncle not unique") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | 	self.current.uncles.Add(uncle.Hash()) | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-23 12:12:49 +01:00
										 |  |  | 	if !self.current.family.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-03-23 12:12:49 +01:00
										 |  |  | 	if self.current.family.Has(uncle.Hash()) { | 
					
						
							|  |  |  | 		return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash())) | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *worker) commitTransaction(tx *types.Transaction) error { | 
					
						
							| 
									
										
										
										
											2015-03-11 16:32:37 +01:00
										 |  |  | 	snap := self.current.state.Copy() | 
					
						
							| 
									
										
										
										
											2015-02-15 16:16:27 +01:00
										 |  |  | 	receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true) | 
					
						
							| 
									
										
										
										
											2015-03-11 16:32:37 +01:00
										 |  |  | 	if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err) || core.IsInvalidTxErr(err)) { | 
					
						
							|  |  |  | 		self.current.state.Set(snap) | 
					
						
							| 
									
										
										
										
											2015-02-04 05:52:59 -08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	self.current.block.AddTransaction(tx) | 
					
						
							|  |  |  | 	self.current.block.AddReceipt(receipt) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-02-28 23:09:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (self *worker) HashRate() int64 { | 
					
						
							|  |  |  | 	var tot int64 | 
					
						
							|  |  |  | 	for _, agent := range self.agents { | 
					
						
							| 
									
										
										
										
											2015-03-20 17:42:09 +01:00
										 |  |  | 		tot += agent.GetHashRate() | 
					
						
							| 
									
										
										
										
											2015-02-28 23:09:49 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return tot | 
					
						
							|  |  |  | } |