github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/btc/target.go (about) 1 package btc 2 3 import ( 4 "math/big" 5 ) 6 7 func SetCompact(nCompact uint32) (res *big.Int) { 8 size := nCompact>>24 9 neg := (nCompact&0x00800000)!=0 10 word := nCompact & 0x007fffff 11 if size <= 3 { 12 word >>= 8*(3-size); 13 res = big.NewInt(int64(word)) 14 } else { 15 res = big.NewInt(int64(word)) 16 res.Lsh(res, uint(8*(size-3))) 17 } 18 if neg { 19 res.Neg(res) 20 } 21 return res 22 } 23 24 25 func GetDifficulty(bits uint32) (diff float64) { 26 shift := int(bits >> 24) & 0xff 27 diff = float64(0x0000ffff) / float64(bits & 0x00ffffff) 28 for shift < 29 { 29 diff *= 256.0 30 shift++ 31 } 32 for shift > 29 { 33 diff /= 256.0 34 shift-- 35 } 36 return 37 } 38 39 40 func GetCompact(b *big.Int) uint32 { 41 42 size := uint32(len(b.Bytes())) 43 var compact uint32 44 45 if size <= 3 { 46 compact = uint32(b.Int64() << uint(8*(3-size))) 47 } else { 48 b = new(big.Int).Rsh(b, uint(8*(size-3))) 49 compact = uint32(b.Int64()) 50 } 51 52 // The 0x00800000 bit denotes the sign. 53 // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. 54 if (compact & 0x00800000) != 0 { 55 compact >>= 8 56 size++ 57 } 58 compact |= size << 24 59 if b.Cmp(big.NewInt(0)) < 0 { 60 compact |= 0x00800000 61 } 62 return compact 63 } 64 65 66 func CheckProofOfWork(hash *Uint256, bits uint32) bool { 67 return hash.BigInt().Cmp(SetCompact(bits)) <= 0 68 }