// This example demonstrates how to convert the compact "bits" in a block header // which represent the target difficulty to a big integer and display it using // the typical hex notation. func ExampleCompactToBig() { // Convert the bits from block 300000 in the main Decred block chain. bits := uint32(419465580) targetDifficulty := blockchain.CompactToBig(bits) // Display it in hex. fmt.Printf("%064x\n", targetDifficulty.Bytes()) // Output: // 0000000000000000896c00000000000000000000000000000000000000000000 }
func (s *ProxyServer) fetchPendingBlock(data string) (uint64, *big.Int, error) { blockNumberStr, err := hex.DecodeString(data[256:264]) if err != nil { log.Println("Can't parse pending block number") // TODO: valami alap difficultyt!! return 0, nil, err } blockNumber := binary.LittleEndian.Uint32(blockNumberStr) blockDiffStr, err := hex.DecodeString(data[232:240]) if err != nil { log.Println("Can't parse pending block difficulty") return 0, nil, err } blockDiff := binary.LittleEndian.Uint32(blockDiffStr) return uint64(blockNumber), blockchain.CompactToBig(blockDiff), nil }
// getDifficultyRatio returns the proof-of-work difficulty as a multiple of the // minimum difficulty using the passed bits field from the header of a block. func GetDifficultyRatio(bits uint32) float64 { // The minimum difficulty is the max possible proof-of-work limit bits // converted back to a number. Note this is not the same as the the // proof of work limit directly because the block difficulty is encoded // in a block with the compact form which loses precision. max := PowLimit // blockchain.CompactToBig(chaincfg.TestNetParams.PowLimitBits) target := blockchain.CompactToBig(bits) difficulty := new(big.Rat).SetFrac(max, target) outString := difficulty.FloatString(8) diff, err := strconv.ParseFloat(outString, 64) if err != nil { //rpcsLog.Errorf("Cannot get difficulty: %v", err) return 0 } return diff }
func TestCompactToBig(t *testing.T) { tests := []struct { in uint32 out int64 }{ {10000000, 0}, } for x, test := range tests { n := blockchain.CompactToBig(test.in) want := big.NewInt(test.out) if n.Cmp(want) != 0 { t.Errorf("TestCompactToBig test #%d failed: got %d want %d\n", x, n.Int64(), want.Int64()) return } } }
// 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 }