/* calcDiff returns a bool given two block headers. This bool is true if the correct dificulty adjustment is seen in the "next" header. Only feed it headers n-2016 and n-1, otherwise it will calculate a difficulty when no adjustment should take place, and return false. Note that the epoch is actually 2015 blocks long, which is confusing. */ func calcDiffAdjust(start, end wire.BlockHeader, p *chaincfg.Params) uint32 { duration := end.Timestamp.UnixNano() - start.Timestamp.UnixNano() if duration < minRetargetTimespan { log.Printf("whoa there, block %s off-scale high 4X diff adjustment!", end.BlockSha().String()) duration = minRetargetTimespan } else if duration > maxRetargetTimespan { log.Printf("Uh-oh! block %s off-scale low 0.25X diff adjustment!\n", end.BlockSha().String()) duration = maxRetargetTimespan } // calculation of new 32-byte difficulty target // first turn the previous target into a big int prevTarget := blockchain.CompactToBig(start.Bits) // new target is old * duration... newTarget := new(big.Int).Mul(prevTarget, big.NewInt(duration)) // divided by 2 weeks newTarget.Div(newTarget, big.NewInt(int64(targetTimespan))) // clip again if above minimum target (too easy) if newTarget.Cmp(p.PowLimit) > 0 { newTarget.Set(p.PowLimit) } // calculate and return 4-byte 'bits' difficulty from 32-byte target return blockchain.BigToCompact(newTarget) }
// This example demonstrates how to convert a target difficulty into the compact // "bits" in a block header which represent that target difficulty . func ExampleBigToCompact() { // Convert the target difficulty from block 300000 in the main block // chain to compact form. t := "0000000000000000896c00000000000000000000000000000000000000000000" targetDifficulty, success := new(big.Int).SetString(t, 16) if !success { fmt.Println("invalid target difficulty") return } bits := blockchain.BigToCompact(targetDifficulty) fmt.Println(bits) // Output: // 419465580 }
func TestBigToCompact(t *testing.T) { tests := []struct { in int64 out uint32 }{ {0, 0}, {-1, 25231360}, } for x, test := range tests { n := big.NewInt(test.in) r := blockchain.BigToCompact(n) if r != test.out { t.Errorf("TestBigToCompact test #%d failed: got %d want %d\n", x, r, test.out) return } } }