miner.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. This file is part of go-ethereum
  3. go-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. go-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /**
  15. * @authors
  16. * Jeffrey Wilcke <i@jev.io>
  17. * @date 2014
  18. *
  19. */
  20. package miner
  21. import (
  22. "math/big"
  23. "sort"
  24. "github.com/ethereum/go-ethereum"
  25. "github.com/ethereum/go-ethereum/ethutil"
  26. "github.com/ethereum/go-ethereum/chain"
  27. "github.com/ethereum/go-ethereum/chain/types"
  28. "github.com/ethereum/go-ethereum/event"
  29. "github.com/ethereum/go-ethereum/logger"
  30. "github.com/ethereum/go-ethereum/wire"
  31. )
  32. type LocalTx struct {
  33. To []byte `json:"to"`
  34. Data []byte `json:"data"`
  35. Gas string `json:"gas"`
  36. GasPrice string `json:"gasPrice"`
  37. Value string `json:"value"`
  38. }
  39. func (self *LocalTx) Sign(key []byte) *types.Transaction {
  40. return nil
  41. }
  42. var minerlogger = logger.NewLogger("MINER")
  43. type Miner struct {
  44. eth *eth.Ethereum
  45. events event.Subscription
  46. uncles types.Blocks
  47. localTxs map[int]*LocalTx
  48. localTxId int
  49. pow chain.PoW
  50. quitCh chan struct{}
  51. powQuitCh chan struct{}
  52. Coinbase []byte
  53. mining bool
  54. MinAcceptedGasPrice *big.Int
  55. }
  56. func New(coinbase []byte, eth *eth.Ethereum) *Miner {
  57. return &Miner{
  58. eth: eth,
  59. powQuitCh: make(chan struct{}),
  60. pow: &chain.EasyPow{},
  61. mining: false,
  62. localTxs: make(map[int]*LocalTx),
  63. MinAcceptedGasPrice: big.NewInt(10000000000000),
  64. Coinbase: coinbase,
  65. }
  66. }
  67. func (self *Miner) GetPow() chain.PoW {
  68. return self.pow
  69. }
  70. func (self *Miner) AddLocalTx(tx *LocalTx) int {
  71. minerlogger.Infof("Added local tx (%x %v / %v)\n", tx.To[0:4], tx.GasPrice, tx.Value)
  72. self.localTxId++
  73. self.localTxs[self.localTxId] = tx
  74. self.eth.EventMux().Post(tx)
  75. return self.localTxId
  76. }
  77. func (self *Miner) RemoveLocalTx(id int) {
  78. if tx := self.localTxs[id]; tx != nil {
  79. minerlogger.Infof("Removed local tx (%x %v / %v)\n", tx.To[0:4], tx.GasPrice, tx.Value)
  80. }
  81. self.eth.EventMux().Post(&LocalTx{})
  82. delete(self.localTxs, id)
  83. }
  84. func (self *Miner) Start() {
  85. if self.mining {
  86. return
  87. }
  88. minerlogger.Infoln("Starting mining operations")
  89. self.mining = true
  90. self.quitCh = make(chan struct{})
  91. self.powQuitCh = make(chan struct{})
  92. mux := self.eth.EventMux()
  93. self.events = mux.Subscribe(chain.NewBlockEvent{}, chain.TxPreEvent{}, &LocalTx{})
  94. go self.update()
  95. go self.mine()
  96. }
  97. func (self *Miner) Stop() {
  98. if !self.mining {
  99. return
  100. }
  101. self.mining = false
  102. minerlogger.Infoln("Stopping mining operations")
  103. self.events.Unsubscribe()
  104. close(self.quitCh)
  105. close(self.powQuitCh)
  106. }
  107. func (self *Miner) Mining() bool {
  108. return self.mining
  109. }
  110. func (self *Miner) update() {
  111. out:
  112. for {
  113. select {
  114. case event := <-self.events.Chan():
  115. switch event := event.(type) {
  116. case chain.NewBlockEvent:
  117. block := event.Block
  118. if self.eth.ChainManager().HasBlock(block.Hash()) {
  119. self.reset()
  120. self.eth.TxPool().RemoveSet(block.Transactions())
  121. go self.mine()
  122. } else if true {
  123. // do uncle stuff
  124. }
  125. case chain.TxPreEvent, *LocalTx:
  126. self.reset()
  127. go self.mine()
  128. }
  129. case <-self.quitCh:
  130. break out
  131. }
  132. }
  133. }
  134. func (self *Miner) reset() {
  135. println("reset")
  136. close(self.powQuitCh)
  137. self.powQuitCh = make(chan struct{})
  138. }
  139. func (self *Miner) mine() {
  140. var (
  141. blockManager = self.eth.BlockManager()
  142. chainMan = self.eth.ChainManager()
  143. block = chainMan.NewBlock(self.Coinbase)
  144. )
  145. block.MinGasPrice = self.MinAcceptedGasPrice
  146. // Apply uncles
  147. if len(self.uncles) > 0 {
  148. block.SetUncles(self.uncles)
  149. }
  150. parent := chainMan.GetBlock(block.PrevHash)
  151. coinbase := block.State().GetOrNewStateObject(block.Coinbase)
  152. coinbase.SetGasPool(block.CalcGasLimit(parent))
  153. transactions := self.finiliseTxs()
  154. // Accumulate all valid transactions and apply them to the new state
  155. // Error may be ignored. It's not important during mining
  156. receipts, txs, _, erroneous, err := blockManager.ProcessTransactions(coinbase, block.State(), block, block, transactions)
  157. if err != nil {
  158. minerlogger.Debugln(err)
  159. }
  160. self.eth.TxPool().RemoveSet(erroneous)
  161. block.SetTransactions(txs)
  162. block.SetReceipts(receipts)
  163. // Accumulate the rewards included for this block
  164. blockManager.AccumelateRewards(block.State(), block, parent)
  165. block.State().Update()
  166. minerlogger.Infof("Mining on block. Includes %v transactions", len(transactions))
  167. // Find a valid nonce
  168. nonce := self.pow.Search(block, self.powQuitCh)
  169. if nonce != nil {
  170. block.Nonce = nonce
  171. lchain := chain.NewChain(types.Blocks{block})
  172. _, err := chainMan.TestChain(lchain)
  173. if err != nil {
  174. minerlogger.Infoln(err)
  175. } else {
  176. chainMan.InsertChain(lchain)
  177. //self.eth.EventMux().Post(chain.NewBlockEvent{block})
  178. self.eth.Broadcast(wire.MsgBlockTy, []interface{}{block.Value().Val})
  179. minerlogger.Infof("🔨 Mined block %x\n", block.Hash())
  180. minerlogger.Infoln(block)
  181. }
  182. go self.mine()
  183. }
  184. }
  185. func (self *Miner) finiliseTxs() types.Transactions {
  186. // Sort the transactions by nonce in case of odd network propagation
  187. var txs types.Transactions
  188. state := self.eth.BlockManager().TransState()
  189. // XXX This has to change. Coinbase is, for new, same as key.
  190. key := self.eth.KeyManager()
  191. for _, ltx := range self.localTxs {
  192. tx := types.NewTransactionMessage(ltx.To, ethutil.Big(ltx.Value), ethutil.Big(ltx.Gas), ethutil.Big(ltx.GasPrice), ltx.Data)
  193. tx.Nonce = state.GetNonce(self.Coinbase)
  194. state.SetNonce(self.Coinbase, tx.Nonce+1)
  195. tx.Sign(key.PrivateKey())
  196. txs = append(txs, tx)
  197. }
  198. txs = append(txs, self.eth.TxPool().CurrentTransactions()...)
  199. sort.Sort(types.TxByNonce{txs})
  200. return txs
  201. }