Skip to content

Commit cd36e80

Browse files
committed
miner: add restart methods
node: restart miner on new full tip
1 parent 6cae7ec commit cd36e80

4 files changed

Lines changed: 64 additions & 21 deletions

File tree

core/nakamoto/blockdag_client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ func (dag *BlockDAG) GetLatestFullTip() (Block, error) {
295295
296296
-- Case 2: Blocks without transactions.
297297
-- If a block has no transactions, then it is fully downloaded and is considered for the "full tip".
298+
-- TODO: A block NEVER has 0 transactions! There is always the coinbase.
298299
SELECT b.hash, b.acc_work
299300
FROM blocks b
300301
WHERE b.num_transactions = 0

core/nakamoto/mempool.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,8 @@ func (m *Mempool) GetBundle(max uint) []RawTransaction {
130130

131131
return bundle
132132
}
133+
134+
// Regenerates the mempool from the current state of the chain, removing transactions that are already in the chain.
135+
func (m *Mempool) Regenerate() {
136+
// TODO.
137+
}

core/nakamoto/miner.go

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
237269
func (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
}

core/nakamoto/node.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,10 @@ func (n *Node) setup() {
198198
n.stateLog.Printf("rebuild-state completed duration=%s n_blocks=%d\n", duration.String(), n.Dag.FullTip.Height)
199199

200200
// 2. Regenerate current mempool. Tx set should not include any txs that are in the chain.
201+
n.Mempool.Regenerate()
202+
201203
// 3. Restart miner.
202-
// TODO.
204+
n.Miner.RestartWithNewPuzzle()
203205
}
204206

205207
// Listen for new transactions and add them to the mempool.

0 commit comments

Comments
 (0)