@@ -46,6 +46,10 @@ type Miner struct {
4646 IsRunning bool
4747 GraffitiTag [32 ]byte
4848
49+ // Miner state.
50+ stopCh chan bool
51+ puzzles chan POWPuzzle
52+
4953 // Mutex.
5054 mutex sync.Mutex
5155
@@ -99,7 +103,13 @@ type POWPuzzle struct {
99103 solution big.Int
100104}
101105
102- func (miner * Miner ) MineWithStatus (hashrateChannel chan float64 , solutionChannel chan POWPuzzle , puzzleChannel chan POWPuzzle ) (big.Int , error ) {
106+ // Miner thread:
107+ // States:
108+ // - waiting for puzzle
109+ // - mining puzzle
110+ // - puzzle solved
111+ // - restart on new puzzle
112+ func mineWithStatus (log * log.Logger , hashrates chan float64 , solutions chan POWPuzzle , puzzles chan POWPuzzle , stopCh chan bool ) (big.Int , error ) {
103113 // Execute in 3s increments.
104114 lastHashrateMeasurement := Timestamp ()
105115 numHashes := 0
@@ -118,7 +128,7 @@ func (miner *Miner) MineWithStatus(hashrateChannel chan float64, solutionChannel
118128 now := Timestamp ()
119129 duration := now - lastHashrateMeasurement
120130 hashrate := float64 (numHashes ) / float64 (duration / 1000 )
121- hashrateChannel <- hashrate
131+ hashrates <- hashrate
122132 numHashes = 0
123133 lastHashrateMeasurement = now
124134 }
@@ -127,12 +137,12 @@ func (miner *Miner) MineWithStatus(hashrateChannel chan float64, solutionChannel
127137 // Routine: Mine.
128138 for {
129139 var i uint64 = 0
130- miner . log .Println ("Waiting for new puzzle" )
131- puzzle := <- puzzleChannel
140+ log .Println ("Waiting for new puzzle" )
141+ puzzle := <- puzzles
132142 block := puzzle .block
133143 nonce := puzzle .startNonce
134144 target := puzzle .target
135- miner . log .Printf ("New puzzle block=%s target=%s\n " , block .HashStr (), target .String ())
145+ log .Printf ("New puzzle block=%s target=%s\n " , block .HashStr (), target .String ())
136146
137147 // Loop: mine 1 hash.
138148 for {
@@ -151,21 +161,24 @@ func (miner *Miner) MineWithStatus(hashrateChannel chan float64, solutionChannel
151161
152162 // Check solution: hash < target.
153163 if guess .Cmp (& target ) == - 1 {
154- miner . log .Printf ("Puzzle solved: iterations=%d\n " , i )
164+ log .Printf ("Puzzle solved: iterations=%d\n " , i )
155165
156166 puzzle .solution = nonce
157- solutionChannel <- puzzle
167+ solutions <- puzzle
158168 break
159169 }
160170
161171 // Check if new puzzle has been received.
162172 select {
163- case newPuzzle := <- puzzleChannel :
173+ case newPuzzle := <- puzzles :
164174 puzzle = newPuzzle
165175 block = puzzle .block
166176 nonce = puzzle .startNonce
167177 target = puzzle .target
168- miner .log .Printf ("New puzzle block=%s target=%s\n " , block .HashStr (), target .String ())
178+ log .Printf ("New puzzle block=%s target=%s\n " , block .HashStr (), target .String ())
179+ case <- stopCh :
180+ log .Println ("Stopping miner" )
181+ return nonce , nil
169182 default :
170183 // Do nothing.
171184 }
@@ -234,6 +247,25 @@ func (miner *Miner) MakeNewPuzzle() POWPuzzle {
234247 return puzzle
235248}
236249
250+ func (miner * Miner ) Stop () {
251+ miner .mutex .Lock ()
252+ if ! miner .IsRunning {
253+ miner .log .Printf ("Miner not running" )
254+ miner .mutex .Unlock ()
255+ return
256+ }
257+ miner .IsRunning = false
258+ miner .mutex .Unlock ()
259+
260+ miner .log .Println ("Sent stop signal to miner" )
261+ miner .stopCh <- true
262+ }
263+
264+ // Send new puzzle to miner thread, based off the latest full tip.
265+ func (miner * Miner ) RestartWithNewPuzzle () {
266+ miner .puzzles <- miner .MakeNewPuzzle ()
267+ }
268+
237269func (miner * Miner ) Start (mineMaxBlocks int64 ) []RawBlock {
238270 miner .mutex .Lock ()
239271 if miner .IsRunning {
@@ -243,26 +275,29 @@ func (miner *Miner) Start(mineMaxBlocks int64) []RawBlock {
243275 miner .IsRunning = true
244276 miner .mutex .Unlock ()
245277
246- // The next tip channel.
247- // next_tip := make(chan Block)
248- // block_solutions := make(chan Block)
249- hashrateChannel := make (chan float64 , 1 )
250- puzzleChannel := make (chan POWPuzzle , 1 )
251- solutionChannel := make (chan POWPuzzle , 1 )
278+ // Set miner thread state.
279+ hashrates := make (chan float64 , 1 )
280+ puzzles := make (chan POWPuzzle , 1 )
281+ solutions := make (chan POWPuzzle , 1 )
282+ stopCh := make (chan bool , 1 )
283+
284+ // Set miner state.
285+ miner .stopCh = stopCh
286+ miner .puzzles = puzzles
252287
253- go miner .MineWithStatus ( hashrateChannel , solutionChannel , puzzleChannel )
288+ go mineWithStatus ( miner .log , hashrates , solutions , puzzles , stopCh )
254289
255290 var blocksMined int64 = 0
256291 mined := []RawBlock {}
257292
258- puzzleChannel <- miner .MakeNewPuzzle ()
293+ puzzles <- miner .MakeNewPuzzle ()
259294 for {
260295 select {
261- case hashrate := <- hashrateChannel :
296+ case hashrate := <- hashrates :
262297 // Print iterations using commas.
263298 p := message .NewPrinter (language .English )
264299 miner .log .Printf (p .Sprintf ("Hashrate: %.2f H/s\n " , hashrate ))
265- case puzzle := <- solutionChannel :
300+ case puzzle := <- solutions :
266301 miner .log .Println ("Received solution" )
267302
268303 raw := puzzle .block
@@ -288,7 +323,7 @@ func (miner *Miner) Start(mineMaxBlocks int64) []RawBlock {
288323
289324 miner .log .Println ("Making new puzzle" )
290325 miner .log .Println ("New puzzle ready" )
291- puzzleChannel <- miner .MakeNewPuzzle ()
326+ puzzles <- miner .MakeNewPuzzle ()
292327 }
293328 }
294329}
0 commit comments