From 5af4ff985dc43b648bdc96394a3bd96d9658ae0a Mon Sep 17 00:00:00 2001
From: obscuren <geffobscura@gmail.com>
Date: Fri, 31 Oct 2014 14:56:42 +0100
Subject: ethminer => miner

---
 cmd/mist/gui.go  |  10 +--
 cmd/utils/cmd.go |  18 ++---
 miner/miner.go   | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 231 insertions(+), 14 deletions(-)
 create mode 100644 miner/miner.go

diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go
index d309e0a9b..d6f6832e2 100644
--- a/cmd/mist/gui.go
+++ b/cmd/mist/gui.go
@@ -33,9 +33,9 @@ import (
 	"github.com/ethereum/go-ethereum"
 	"github.com/ethereum/go-ethereum/chain"
 	"github.com/ethereum/go-ethereum/ethdb"
-	"github.com/ethereum/go-ethereum/ethminer"
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
+	"github.com/ethereum/go-ethereum/miner"
 	"github.com/ethereum/go-ethereum/wire"
 	"github.com/ethereum/go-ethereum/xeth"
 	"gopkg.in/qml.v1"
@@ -92,7 +92,7 @@ type Gui struct {
 
 	plugins map[string]plugin
 
-	miner  *ethminer.Miner
+	miner  *miner.Miner
 	stdLog logger.LogSystem
 }
 
@@ -410,7 +410,7 @@ func (gui *Gui) update() {
 		chain.NewBlockEvent{},
 		chain.TxPreEvent{},
 		chain.TxPostEvent{},
-		ethminer.Event{},
+		miner.Event{},
 	)
 
 	// nameReg := gui.pipe.World().Config().Get("NameReg")
@@ -469,8 +469,8 @@ func (gui *Gui) update() {
 				case eth.PeerListEvent:
 					gui.setPeerInfo()
 
-				case ethminer.Event:
-					if ev.Type == ethminer.Started {
+				case miner.Event:
+					if ev.Type == miner.Started {
 						gui.miner = ev.Miner
 					} else {
 						gui.miner = nil
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 5313b8fad..ef2ce8b47 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -16,9 +16,9 @@ import (
 	"github.com/ethereum/go-ethereum"
 	"github.com/ethereum/go-ethereum/crypto"
 	"github.com/ethereum/go-ethereum/ethdb"
-	"github.com/ethereum/go-ethereum/ethminer"
 	"github.com/ethereum/go-ethereum/ethutil"
 	"github.com/ethereum/go-ethereum/logger"
+	"github.com/ethereum/go-ethereum/miner"
 	"github.com/ethereum/go-ethereum/rpc"
 	"github.com/ethereum/go-ethereum/wire"
 	"github.com/ethereum/go-ethereum/xeth"
@@ -252,10 +252,10 @@ func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
 	}
 }
 
-var miner *ethminer.Miner
+var gminer *miner.Miner
 
-func GetMiner() *ethminer.Miner {
-	return miner
+func GetMiner() *miner.Miner {
+	return gminer
 }
 
 func StartMining(ethereum *eth.Ethereum) bool {
@@ -265,15 +265,15 @@ func StartMining(ethereum *eth.Ethereum) bool {
 
 		go func() {
 			clilogger.Infoln("Start mining")
-			if miner == nil {
-				miner = ethminer.NewDefaultMiner(addr, ethereum)
+			if gminer == nil {
+				gminer = miner.NewDefaultMiner(addr, ethereum)
 			}
 			// Give it some time to connect with peers
 			time.Sleep(3 * time.Second)
 			for !ethereum.IsUpToDate() {
 				time.Sleep(5 * time.Second)
 			}
-			miner.Start()
+			gminer.Start()
 		}()
 		RegisterInterrupt(func(os.Signal) {
 			StopMining(ethereum)
@@ -297,8 +297,8 @@ func FormatTransactionData(data string) []byte {
 }
 
 func StopMining(ethereum *eth.Ethereum) bool {
-	if ethereum.Mining && miner != nil {
-		miner.Stop()
+	if ethereum.Mining && gminer != nil {
+		gminer.Stop()
 		clilogger.Infoln("Stopped mining")
 		ethereum.Mining = false
 
diff --git a/miner/miner.go b/miner/miner.go
new file mode 100644
index 000000000..b11bd9532
--- /dev/null
+++ b/miner/miner.go
@@ -0,0 +1,217 @@
+package miner
+
+import (
+	"bytes"
+	"sort"
+
+	"github.com/ethereum/go-ethereum/chain"
+	"github.com/ethereum/go-ethereum/event"
+	"github.com/ethereum/go-ethereum/logger"
+	"github.com/ethereum/go-ethereum/wire"
+)
+
+var minerlogger = logger.NewLogger("MINER")
+
+type Miner struct {
+	pow      chain.PoW
+	ethereum chain.EthManager
+	coinbase []byte
+	txs      chain.Transactions
+	uncles   []*chain.Block
+	block    *chain.Block
+
+	events      event.Subscription
+	powQuitChan chan struct{}
+	powDone     chan struct{}
+
+	turbo bool
+}
+
+const (
+	Started = iota
+	Stopped
+)
+
+type Event struct {
+	Type  int // Started || Stopped
+	Miner *Miner
+}
+
+func (self *Miner) GetPow() chain.PoW {
+	return self.pow
+}
+
+func NewDefaultMiner(coinbase []byte, ethereum chain.EthManager) *Miner {
+	miner := Miner{
+		pow:      &chain.EasyPow{},
+		ethereum: ethereum,
+		coinbase: coinbase,
+	}
+
+	return &miner
+}
+
+func (self *Miner) ToggleTurbo() {
+	self.turbo = !self.turbo
+
+	self.pow.Turbo(self.turbo)
+}
+
+func (miner *Miner) Start() {
+
+	// Insert initial TXs in our little miner 'pool'
+	miner.txs = miner.ethereum.TxPool().Flush()
+	miner.block = miner.ethereum.ChainManager().NewBlock(miner.coinbase)
+
+	mux := miner.ethereum.EventMux()
+	miner.events = mux.Subscribe(chain.NewBlockEvent{}, chain.TxPreEvent{})
+
+	// Prepare inital block
+	//miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State())
+	go miner.listener()
+
+	minerlogger.Infoln("Started")
+	mux.Post(Event{Started, miner})
+}
+
+func (miner *Miner) Stop() {
+	minerlogger.Infoln("Stopping...")
+	miner.events.Unsubscribe()
+	miner.ethereum.EventMux().Post(Event{Stopped, miner})
+}
+
+func (miner *Miner) listener() {
+	miner.startMining()
+
+	for {
+		select {
+		case event := <-miner.events.Chan():
+			switch event := event.(type) {
+			case chain.NewBlockEvent:
+				miner.stopMining()
+
+				block := event.Block
+				//minerlogger.Infoln("Got new block via Reactor")
+				if bytes.Compare(miner.ethereum.ChainManager().CurrentBlock.Hash(), block.Hash()) == 0 {
+					// TODO: Perhaps continue mining to get some uncle rewards
+					//minerlogger.Infoln("New top block found resetting state")
+
+					// Filter out which Transactions we have that were not in this block
+					var newtxs []*chain.Transaction
+					for _, tx := range miner.txs {
+						found := false
+						for _, othertx := range block.Transactions() {
+							if bytes.Compare(tx.Hash(), othertx.Hash()) == 0 {
+								found = true
+							}
+						}
+						if found == false {
+							newtxs = append(newtxs, tx)
+						}
+					}
+					miner.txs = newtxs
+				} else {
+					if bytes.Compare(block.PrevHash, miner.ethereum.ChainManager().CurrentBlock.PrevHash) == 0 {
+						minerlogger.Infoln("Adding uncle block")
+						miner.uncles = append(miner.uncles, block)
+					}
+				}
+				miner.startMining()
+
+			case chain.TxPreEvent:
+				miner.stopMining()
+
+				found := false
+				for _, ctx := range miner.txs {
+					if found = bytes.Compare(ctx.Hash(), event.Tx.Hash()) == 0; found {
+						break
+					}
+
+					miner.startMining()
+				}
+				if found == false {
+					// Undo all previous commits
+					miner.block.Undo()
+					// Apply new transactions
+					miner.txs = append(miner.txs, event.Tx)
+				}
+			}
+
+		case <-miner.powDone:
+			miner.startMining()
+		}
+	}
+}
+
+func (miner *Miner) startMining() {
+	if miner.powDone == nil {
+		miner.powDone = make(chan struct{})
+	}
+	miner.powQuitChan = make(chan struct{})
+	go miner.mineNewBlock()
+}
+
+func (miner *Miner) stopMining() {
+	println("stop mining")
+	_, isopen := <-miner.powQuitChan
+	if isopen {
+		close(miner.powQuitChan)
+	}
+	//<-miner.powDone
+}
+
+func (self *Miner) mineNewBlock() {
+	stateManager := self.ethereum.StateManager()
+
+	self.block = self.ethereum.ChainManager().NewBlock(self.coinbase)
+
+	// Apply uncles
+	if len(self.uncles) > 0 {
+		self.block.SetUncles(self.uncles)
+	}
+
+	// Sort the transactions by nonce in case of odd network propagation
+	sort.Sort(chain.TxByNonce{self.txs})
+
+	// Accumulate all valid transactions and apply them to the new state
+	// Error may be ignored. It's not important during mining
+	parent := self.ethereum.ChainManager().GetBlock(self.block.PrevHash)
+	coinbase := self.block.State().GetOrNewStateObject(self.block.Coinbase)
+	coinbase.SetGasPool(self.block.CalcGasLimit(parent))
+	receipts, txs, unhandledTxs, erroneous, err := stateManager.ProcessTransactions(coinbase, self.block.State(), self.block, self.block, self.txs)
+	if err != nil {
+		minerlogger.Debugln(err)
+	}
+	self.ethereum.TxPool().RemoveSet(erroneous)
+	self.txs = append(txs, unhandledTxs...)
+
+	self.block.SetTransactions(txs)
+	self.block.SetReceipts(receipts)
+
+	// Accumulate the rewards included for this block
+	stateManager.AccumelateRewards(self.block.State(), self.block, parent)
+
+	self.block.State().Update()
+
+	minerlogger.Infof("Mining on block. Includes %v transactions", len(self.txs))
+
+	// Find a valid nonce
+	nonce := self.pow.Search(self.block, self.powQuitChan)
+	if nonce != nil {
+		self.block.Nonce = nonce
+		err := self.ethereum.StateManager().Process(self.block)
+		if err != nil {
+			minerlogger.Infoln(err)
+		} else {
+			self.ethereum.Broadcast(wire.MsgBlockTy, []interface{}{self.block.Value().Val})
+			minerlogger.Infof("🔨  Mined block %x\n", self.block.Hash())
+			minerlogger.Infoln(self.block)
+			// Gather the new batch of transactions currently in the tx pool
+			self.txs = self.ethereum.TxPool().CurrentTransactions()
+			self.ethereum.EventMux().Post(chain.NewBlockEvent{self.block})
+		}
+
+		// Continue mining on the next block
+		self.startMining()
+	}
+}
-- 
cgit v1.2.3