279 lines
6.6 KiB
Go
279 lines
6.6 KiB
Go
package types
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"errors"
|
|
"github.com/holiman/uint256"
|
|
"lukechampine.com/uint128"
|
|
"math/big"
|
|
"math/bits"
|
|
"strings"
|
|
)
|
|
|
|
const DifficultySize = 16
|
|
|
|
var ZeroDifficulty = Difficulty(uint128.Zero)
|
|
var MaxDifficulty = Difficulty(uint128.Max)
|
|
|
|
type Difficulty uint128.Uint128
|
|
|
|
func (d Difficulty) IsZero() bool {
|
|
return uint128.Uint128(d).IsZero()
|
|
}
|
|
|
|
func (d Difficulty) Equals(v Difficulty) bool {
|
|
return uint128.Uint128(d).Equals(uint128.Uint128(v))
|
|
}
|
|
|
|
func (d Difficulty) Equals64(v uint64) bool {
|
|
return uint128.Uint128(d).Equals64(v)
|
|
}
|
|
|
|
func (d Difficulty) Cmp(v Difficulty) int {
|
|
return uint128.Uint128(d).Cmp(uint128.Uint128(v))
|
|
}
|
|
|
|
func (d Difficulty) Cmp64(v uint64) int {
|
|
return uint128.Uint128(d).Cmp64(v)
|
|
}
|
|
|
|
func (d Difficulty) And(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).And(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) And64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).And64(v))
|
|
}
|
|
|
|
func (d Difficulty) Or(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Or(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) Or64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Or64(v))
|
|
}
|
|
|
|
func (d Difficulty) Xor(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Xor(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) Xor64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Xor64(v))
|
|
}
|
|
|
|
func (d Difficulty) Add(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Add(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) AddWrap(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).AddWrap(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) Add64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Add64(v))
|
|
}
|
|
|
|
func (d Difficulty) AddWrap64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).AddWrap64(v))
|
|
}
|
|
|
|
func (d Difficulty) Sub(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Sub(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) SubWrap(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).SubWrap(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) Sub64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Sub64(v))
|
|
}
|
|
|
|
func (d Difficulty) SubWrap64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).SubWrap64(v))
|
|
}
|
|
|
|
func (d Difficulty) Mul(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Mul(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) MulWrap(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).MulWrap(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) Mul64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Mul64(v))
|
|
}
|
|
|
|
func (d Difficulty) MulWrap64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).MulWrap64(v))
|
|
}
|
|
|
|
func (d Difficulty) Div(v Difficulty) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Div(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) Div64(v uint64) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Div64(v))
|
|
}
|
|
|
|
func (d Difficulty) QuoRem(v Difficulty) (q, r Difficulty) {
|
|
qq, rr := uint128.Uint128(d).QuoRem(uint128.Uint128(v))
|
|
return Difficulty(qq), Difficulty(rr)
|
|
}
|
|
|
|
func (d Difficulty) QuoRem64(v uint64) (q Difficulty, r uint64) {
|
|
qq, rr := uint128.Uint128(d).QuoRem64(v)
|
|
return Difficulty(qq), rr
|
|
}
|
|
|
|
func (d Difficulty) Mod(v Difficulty) (r Difficulty) {
|
|
return Difficulty(uint128.Uint128(d).Mod(uint128.Uint128(v)))
|
|
}
|
|
|
|
func (d Difficulty) Mod64(v uint64) (r uint64) {
|
|
return uint128.Uint128(d).Mod64(v)
|
|
}
|
|
|
|
func (d Difficulty) Lsh(n uint) (s Difficulty) {
|
|
return Difficulty(uint128.Uint128(d).Lsh(n))
|
|
}
|
|
|
|
func (d Difficulty) Rsh(n uint) (s Difficulty) {
|
|
return Difficulty(uint128.Uint128(d).Rsh(n))
|
|
}
|
|
|
|
func (d Difficulty) LeadingZeros() int {
|
|
return uint128.Uint128(d).LeadingZeros()
|
|
}
|
|
|
|
func (d Difficulty) TrailingZeros() int {
|
|
return uint128.Uint128(d).TrailingZeros()
|
|
}
|
|
|
|
func (d Difficulty) OnesCount() int {
|
|
return uint128.Uint128(d).OnesCount()
|
|
}
|
|
|
|
func (d Difficulty) RotateLeft(k int) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).RotateLeft(k))
|
|
}
|
|
|
|
func (d Difficulty) RotateRight(k int) Difficulty {
|
|
return Difficulty(uint128.Uint128(d).RotateRight(k))
|
|
}
|
|
|
|
func (d Difficulty) Reverse() Difficulty {
|
|
return Difficulty(uint128.Uint128(d).Reverse())
|
|
}
|
|
|
|
func (d Difficulty) ReverseBytes() Difficulty {
|
|
return Difficulty(uint128.Uint128(d).ReverseBytes())
|
|
}
|
|
|
|
func (d Difficulty) Len() int {
|
|
return uint128.Uint128(d).Len()
|
|
}
|
|
|
|
func (d Difficulty) PutBytes(b []byte) {
|
|
uint128.Uint128(d).PutBytes(b)
|
|
}
|
|
|
|
func (d Difficulty) PutBytesBE(b []byte) {
|
|
uint128.Uint128(d).PutBytesBE(b)
|
|
}
|
|
|
|
// Big returns u as a *big.Int.
|
|
func (d Difficulty) Big() *big.Int {
|
|
return uint128.Uint128(d).Big()
|
|
}
|
|
|
|
func (d Difficulty) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(d.String())
|
|
}
|
|
|
|
func DifficultyFromString(s string) (Difficulty, error) {
|
|
if strings.HasPrefix(s, "0x") {
|
|
if buf, err := hex.DecodeString(s[2:]); err != nil {
|
|
return ZeroDifficulty, err
|
|
} else {
|
|
//TODO: check this
|
|
var d [DifficultySize]byte
|
|
copy(d[DifficultySize-len(buf):], buf)
|
|
return DifficultyFromBytes(d[:]), nil
|
|
}
|
|
} else {
|
|
if buf, err := hex.DecodeString(s); err != nil {
|
|
return ZeroDifficulty, err
|
|
} else {
|
|
if len(buf) != DifficultySize {
|
|
return ZeroDifficulty, errors.New("wrong difficulty size")
|
|
}
|
|
|
|
return DifficultyFromBytes(buf), nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func DifficultyFromBytes(buf []byte) Difficulty {
|
|
return Difficulty(uint128.FromBytesBE(buf))
|
|
}
|
|
|
|
func NewDifficulty(lo, hi uint64) Difficulty {
|
|
return Difficulty{Lo: lo, Hi: hi}
|
|
}
|
|
|
|
func DifficultyFrom64(v uint64) Difficulty {
|
|
return NewDifficulty(v, 0)
|
|
}
|
|
|
|
func (d *Difficulty) UnmarshalJSON(b []byte) error {
|
|
var s string
|
|
if err := json.Unmarshal(b, &s); err != nil {
|
|
return err
|
|
}
|
|
|
|
if diff, err := DifficultyFromString(s); err != nil {
|
|
return err
|
|
} else {
|
|
*d = diff
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (d Difficulty) Bytes() []byte {
|
|
buf := make([]byte, DifficultySize)
|
|
d.PutBytesBE(buf)
|
|
return buf
|
|
}
|
|
|
|
func (d Difficulty) String() string {
|
|
return hex.EncodeToString(d.Bytes())
|
|
}
|
|
|
|
func (d Difficulty) StringNumeric() string {
|
|
return uint128.Uint128(d).String()
|
|
}
|
|
|
|
// TODO: remove uint256 dependency as it's unique to this section
|
|
var powBase = uint256.NewInt(0).SetBytes32(bytes.Repeat([]byte{0xff}, 32))
|
|
|
|
func DifficultyFromPoW(powHash Hash) Difficulty {
|
|
if powHash == ZeroHash {
|
|
return ZeroDifficulty
|
|
}
|
|
|
|
pow := uint256.NewInt(0).SetBytes32(powHash[:])
|
|
pow = &uint256.Int{bits.ReverseBytes64(pow[3]), bits.ReverseBytes64(pow[2]), bits.ReverseBytes64(pow[1]), bits.ReverseBytes64(pow[0])}
|
|
|
|
powResult := uint256.NewInt(0).Div(powBase, pow).Bytes32()
|
|
return DifficultyFromBytes(powResult[16:])
|
|
}
|
|
|
|
func (d Difficulty) CheckPoW(pow Hash) bool {
|
|
return DifficultyFromPoW(pow).Cmp(d) >= 0
|
|
}
|