func (b Block) Verify() bool { databytes, err := hex.DecodeString(b.header[0:360]) if err != nil { return false } hash := chainhash.HashFuncH(databytes) hashNum := blockchain.ShaHashToBig(&hash) return hashNum.Cmp(b.difficulty) <= 0 }
/* convert target come from getwork to big integer "ffffffffffffffffffffffffffffffffffffffffffffffffffffff3f00000000" */ func TargetStrToDiff(targetHex string) *big.Int { hashbytes, err := hex.DecodeString(targetHex) if err != nil { return big.NewInt(0) } hash, err := chainhash.NewHash(hashbytes) if err != nil { return big.NewInt(0) } targetdiff := blockchain.ShaHashToBig(hash) if targetdiff.Cmp(big.NewInt(0)) != 0 { targetdiff.Div(PowLimit, targetdiff) } return targetdiff }
// solveBlock attempts to find some combination of a nonce, extra nonce, and // current timestamp which makes the passed block hash to a value less than the // target difficulty. The timestamp is updated periodically and the passed // block is modified with all tweaks during this process. This means that // when the function returns true, the block is ready for submission. // // This function will return early with false when conditions that trigger a // stale block such as a new block showing up or periodically when there are // new transactions and enough time has elapsed without finding a solution. func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, ticker *time.Ticker, quit chan struct{}) bool { blockHeight := int64(msgBlock.Header.Height) // Choose a random extra nonce offset for this block template and // worker. enOffset, err := wire.RandomUint64() if err != nil { minrLog.Errorf("Unexpected error while generating random "+ "extra nonce offset: %v", err) enOffset = 0 } // Create a couple of convenience variables. header := &msgBlock.Header targetDifficulty := blockchain.CompactToBig(header.Bits) // Initial state. lastGenerated := time.Now() lastTxUpdate := m.server.txMemPool.LastUpdated() hashesCompleted := uint64(0) // 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++ { // Get the old nonce values. ens := getCoinbaseExtranonces(msgBlock) ens[2] = extraNonce + enOffset // Update the extra nonce in the block template with the // new value by regenerating the coinbase script and // setting the merkle root to the new value. The UpdateExtraNonce(msgBlock, blockHeight, ens) // 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++ { select { case <-quit: return false case <-ticker.C: m.updateHashes <- hashesCompleted hashesCompleted = 0 // The current block is stale if the memory pool // has been updated since the block template was // generated and it has been at least 3 seconds, // or if it's been one minute. if (lastTxUpdate != m.server.txMemPool.LastUpdated() && time.Now().After(lastGenerated.Add(3*time.Second))) || time.Now().After(lastGenerated.Add(60*time.Second)) { return false } UpdateBlockTime(msgBlock, m.server.blockManager) default: // Non-blocking select to fall through } // Update the nonce and hash the block header. header.Nonce = i hash := header.BlockSha() hashesCompleted += 1 // The block is solved when the new block hash is less // than the target difficulty. Yay! if blockchain.ShaHashToBig(&hash).Cmp(targetDifficulty) <= 0 { m.updateHashes <- hashesCompleted return true } } } return false }