github.com/avence12/go-ethereum@v1.5.10-0.20170320123548-1dfd65f6d047/miner/agent.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package miner 18 19 import ( 20 "fmt" 21 "sync" 22 23 "sync/atomic" 24 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/core/types" 27 "github.com/ethereum/go-ethereum/log" 28 "github.com/ethereum/go-ethereum/pow" 29 ) 30 31 type CpuAgent struct { 32 mu sync.Mutex 33 34 workCh chan *Work 35 quit chan struct{} 36 quitCurrentOp chan struct{} 37 returnCh chan<- *Result 38 39 index int 40 pow pow.PoW 41 42 isMining int32 // isMining indicates whether the agent is currently mining 43 } 44 45 func NewCpuAgent(index int, pow pow.PoW) *CpuAgent { 46 miner := &CpuAgent{ 47 pow: pow, 48 index: index, 49 quit: make(chan struct{}), 50 workCh: make(chan *Work, 1), 51 } 52 53 return miner 54 } 55 56 func (self *CpuAgent) Work() chan<- *Work { return self.workCh } 57 func (self *CpuAgent) Pow() pow.PoW { return self.pow } 58 func (self *CpuAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch } 59 60 func (self *CpuAgent) Stop() { 61 close(self.quit) 62 } 63 64 func (self *CpuAgent) Start() { 65 66 if !atomic.CompareAndSwapInt32(&self.isMining, 0, 1) { 67 return // agent already started 68 } 69 70 go self.update() 71 } 72 73 func (self *CpuAgent) update() { 74 out: 75 for { 76 select { 77 case work := <-self.workCh: 78 self.mu.Lock() 79 if self.quitCurrentOp != nil { 80 close(self.quitCurrentOp) 81 } 82 self.quitCurrentOp = make(chan struct{}) 83 go self.mine(work, self.quitCurrentOp) 84 self.mu.Unlock() 85 case <-self.quit: 86 self.mu.Lock() 87 if self.quitCurrentOp != nil { 88 close(self.quitCurrentOp) 89 self.quitCurrentOp = nil 90 } 91 self.mu.Unlock() 92 break out 93 } 94 } 95 96 done: 97 // Empty work channel 98 for { 99 select { 100 case <-self.workCh: 101 default: 102 close(self.workCh) 103 break done 104 } 105 } 106 107 atomic.StoreInt32(&self.isMining, 0) 108 } 109 110 func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) { 111 log.Debug(fmt.Sprintf("(re)started agent[%d]. mining...\n", self.index)) 112 113 // Mine 114 nonce, mixDigest := self.pow.Search(work.Block, stop) 115 if nonce != 0 { 116 block := work.Block.WithMiningResult(types.EncodeNonce(nonce), common.BytesToHash(mixDigest)) 117 self.returnCh <- &Result{work, block} 118 } else { 119 self.returnCh <- nil 120 } 121 } 122 123 func (self *CpuAgent) GetHashRate() int64 { 124 return int64(self.pow.Hashrate()) 125 }