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  }