mirror of
https://github.com/FlipsideCrypto/dcrd.git
synced 2026-02-06 10:56:47 +00:00
cpuminer: Fix off-by-one issues in nonce handling.
During 32-bit nonce iteration, if a block solution wasn't found, the iterator variable would overflow back to 0, creating an infinite loop, thus continuing the puzzle search without ever updating the extra nonce field. This bug has never been triggered in practice because the code in question has only ever been used with difficulties where a solution exists within the regular nonce space. The extra nonce iteration logic itself was also imperfect in that it wouldn't test a value of exactly 2^64 - 1. The behavior we actually want is to loop through the entire unsigned integer space for both the regular and extra nonces, and for this process to continue forever until a solution is found. Note that periodic updates to the block header timestamp during iteration ensure that unique hashes are generated for subsequent generations of the same nonce values.
This commit is contained in:
parent
cb79063ef8
commit
adff6a0bac
24
cpuminer.go
24
cpuminer.go
@ -250,8 +250,10 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, ticker *time.Ticker, quit
|
||||
|
||||
// Note that the entire extra nonce range is iterated and the offset is
|
||||
// added relying on the fact that overflow will wrap around 0 as
|
||||
// provided by the Go spec.
|
||||
for extraNonce := uint64(0); extraNonce < maxExtraNonce; extraNonce++ {
|
||||
// provided by the Go spec. Furthermore, the break condition has been
|
||||
// intentionally omitted such that the loop will continue forever until
|
||||
// a solution is found.
|
||||
for extraNonce := uint64(0); ; extraNonce++ {
|
||||
// Update the extra nonce in the block template header with the
|
||||
// new value.
|
||||
littleEndian.PutUint64(header.ExtraData[:], extraNonce+enOffset)
|
||||
@ -259,7 +261,15 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, ticker *time.Ticker, quit
|
||||
// Search through the entire nonce range for a solution while
|
||||
// periodically checking for early quit and stale block
|
||||
// conditions along with updates to the speed monitor.
|
||||
for i := uint32(0); i <= maxNonce; i++ {
|
||||
//
|
||||
// This loop differs from the outer one in that it does not run
|
||||
// forever, thus allowing the extraNonce field to be updated
|
||||
// between each successive iteration of the regular nonce
|
||||
// space. Note that this is achieved by placing the break
|
||||
// condition at the end of the code block, as this prevents the
|
||||
// infinite loop that would otherwise occur if we let the for
|
||||
// statement overflow the nonce value back to 0.
|
||||
for nonce := uint32(0); ; nonce++ {
|
||||
select {
|
||||
case <-quit:
|
||||
return false
|
||||
@ -294,7 +304,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, ticker *time.Ticker, quit
|
||||
}
|
||||
|
||||
// Update the nonce and hash the block header.
|
||||
header.Nonce = i
|
||||
header.Nonce = nonce
|
||||
hash := header.BlockHash()
|
||||
hashesCompleted++
|
||||
|
||||
@ -307,10 +317,12 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, ticker *time.Ticker, quit
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if nonce == maxNonce {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// generateBlocks is a worker that is controlled by the miningWorkerController.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user