git.gammaspectra.live/P2Pool/consensus/v3@v3.8.0/types/difficulty.go (about)

     1  package types
     2  
     3  import (
     4  	"database/sql/driver"
     5  	"errors"
     6  	"fmt"
     7  	"git.gammaspectra.live/P2Pool/consensus/v3/utils"
     8  	fasthex "github.com/tmthrgd/go-hex"
     9  	"io"
    10  	"lukechampine.com/uint128"
    11  	"math"
    12  	"math/big"
    13  	"math/bits"
    14  	"strconv"
    15  	"strings"
    16  )
    17  
    18  const DifficultySize = 16
    19  
    20  var ZeroDifficulty = Difficulty(uint128.Zero)
    21  var MaxDifficulty = Difficulty(uint128.Max)
    22  
    23  type Difficulty uint128.Uint128
    24  
    25  func (d Difficulty) IsZero() bool {
    26  	return uint128.Uint128(d).IsZero()
    27  }
    28  
    29  func (d Difficulty) Equals(v Difficulty) bool {
    30  	return uint128.Uint128(d).Equals(uint128.Uint128(v))
    31  }
    32  
    33  func (d Difficulty) Equals64(v uint64) bool {
    34  	return uint128.Uint128(d).Equals64(v)
    35  }
    36  
    37  func (d Difficulty) Cmp(v Difficulty) int {
    38  	//return uint128.Uint128(d).Cmp(uint128.Uint128(v))
    39  	if d == v {
    40  		return 0
    41  	} else if d.Hi < v.Hi || (d.Hi == v.Hi && d.Lo < v.Lo) {
    42  		return -1
    43  	} else {
    44  		return 1
    45  	}
    46  }
    47  
    48  func (d Difficulty) Cmp64(v uint64) int {
    49  	return uint128.Uint128(d).Cmp64(v)
    50  }
    51  
    52  func (d Difficulty) And(v Difficulty) Difficulty {
    53  	return Difficulty(uint128.Uint128(d).And(uint128.Uint128(v)))
    54  }
    55  
    56  func (d Difficulty) And64(v uint64) Difficulty {
    57  	return Difficulty(uint128.Uint128(d).And64(v))
    58  }
    59  
    60  func (d Difficulty) Or(v Difficulty) Difficulty {
    61  	return Difficulty(uint128.Uint128(d).Or(uint128.Uint128(v)))
    62  }
    63  
    64  func (d Difficulty) Or64(v uint64) Difficulty {
    65  	return Difficulty(uint128.Uint128(d).Or64(v))
    66  }
    67  
    68  func (d Difficulty) Xor(v Difficulty) Difficulty {
    69  	return Difficulty(uint128.Uint128(d).Xor(uint128.Uint128(v)))
    70  }
    71  
    72  func (d Difficulty) Xor64(v uint64) Difficulty {
    73  	return Difficulty(uint128.Uint128(d).Xor64(v))
    74  }
    75  
    76  // Add All calls can wrap
    77  func (d Difficulty) Add(v Difficulty) Difficulty {
    78  	//return Difficulty(uint128.Uint128(d).AddWrap(uint128.Uint128(v)))
    79  	lo, carry := bits.Add64(d.Lo, v.Lo, 0)
    80  	hi, _ := bits.Add64(d.Hi, v.Hi, carry)
    81  	return Difficulty{Lo: lo, Hi: hi}
    82  }
    83  
    84  // Add64 All calls can wrap
    85  func (d Difficulty) Add64(v uint64) Difficulty {
    86  	return Difficulty(uint128.Uint128(d).AddWrap64(v))
    87  }
    88  
    89  // Sub All calls can wrap
    90  func (d Difficulty) Sub(v Difficulty) Difficulty {
    91  	return Difficulty(uint128.Uint128(d).SubWrap(uint128.Uint128(v)))
    92  }
    93  
    94  // Sub64 All calls can wrap
    95  func (d Difficulty) Sub64(v uint64) Difficulty {
    96  	return Difficulty(uint128.Uint128(d).SubWrap64(v))
    97  }
    98  
    99  // Mul All calls can wrap
   100  func (d Difficulty) Mul(v Difficulty) Difficulty {
   101  	return Difficulty(uint128.Uint128(d).MulWrap(uint128.Uint128(v)))
   102  }
   103  
   104  // Mul64 All calls can wrap
   105  func (d Difficulty) Mul64(v uint64) Difficulty {
   106  	//return Difficulty(uint128.Uint128(d).MulWrap64(v))
   107  	hi, lo := bits.Mul64(d.Lo, v)
   108  	hi += d.Hi * v
   109  	return Difficulty{Lo: lo, Hi: hi}
   110  }
   111  
   112  func (d Difficulty) Div(v Difficulty) Difficulty {
   113  	return Difficulty(uint128.Uint128(d).Div(uint128.Uint128(v)))
   114  }
   115  
   116  func (d Difficulty) Div64(v uint64) Difficulty {
   117  	return Difficulty(uint128.Uint128(d).Div64(v))
   118  }
   119  
   120  func (d Difficulty) QuoRem(v Difficulty) (q, r Difficulty) {
   121  	qq, rr := uint128.Uint128(d).QuoRem(uint128.Uint128(v))
   122  	return Difficulty(qq), Difficulty(rr)
   123  }
   124  
   125  func (d Difficulty) QuoRem64(v uint64) (q Difficulty, r uint64) {
   126  	qq, rr := uint128.Uint128(d).QuoRem64(v)
   127  	return Difficulty(qq), rr
   128  }
   129  
   130  func (d Difficulty) Mod(v Difficulty) (r Difficulty) {
   131  	return Difficulty(uint128.Uint128(d).Mod(uint128.Uint128(v)))
   132  }
   133  
   134  func (d Difficulty) Mod64(v uint64) (r uint64) {
   135  	return uint128.Uint128(d).Mod64(v)
   136  }
   137  
   138  func (d Difficulty) Lsh(n uint) (s Difficulty) {
   139  	return Difficulty(uint128.Uint128(d).Lsh(n))
   140  }
   141  
   142  func (d Difficulty) Rsh(n uint) (s Difficulty) {
   143  	return Difficulty(uint128.Uint128(d).Rsh(n))
   144  }
   145  
   146  func (d Difficulty) LeadingZeros() int {
   147  	return uint128.Uint128(d).LeadingZeros()
   148  }
   149  
   150  func (d Difficulty) TrailingZeros() int {
   151  	return uint128.Uint128(d).TrailingZeros()
   152  }
   153  
   154  func (d Difficulty) OnesCount() int {
   155  	return uint128.Uint128(d).OnesCount()
   156  }
   157  
   158  func (d Difficulty) RotateLeft(k int) Difficulty {
   159  	return Difficulty(uint128.Uint128(d).RotateLeft(k))
   160  }
   161  
   162  func (d Difficulty) RotateRight(k int) Difficulty {
   163  	return Difficulty(uint128.Uint128(d).RotateRight(k))
   164  }
   165  
   166  func (d Difficulty) Reverse() Difficulty {
   167  	return Difficulty(uint128.Uint128(d).Reverse())
   168  }
   169  
   170  func (d Difficulty) ReverseBytes() Difficulty {
   171  	return Difficulty(uint128.Uint128(d).ReverseBytes())
   172  }
   173  
   174  func (d Difficulty) Len() int {
   175  	return uint128.Uint128(d).Len()
   176  }
   177  
   178  func (d Difficulty) PutBytes(b []byte) {
   179  	uint128.Uint128(d).PutBytes(b)
   180  }
   181  
   182  func (d Difficulty) PutBytesBE(b []byte) {
   183  	uint128.Uint128(d).PutBytesBE(b)
   184  }
   185  
   186  // Big returns u as a *big.Int.
   187  func (d Difficulty) Big() *big.Int {
   188  	return uint128.Uint128(d).Big()
   189  }
   190  
   191  func (d Difficulty) Float64() float64 {
   192  	return float64(d.Lo) + float64(d.Hi)*(float64(math.MaxUint64)+1)
   193  }
   194  
   195  func (d Difficulty) MarshalJSON() ([]byte, error) {
   196  	if d.Hi == 0 {
   197  		return []byte(strconv.FormatUint(d.Lo, 10)), nil
   198  	}
   199  
   200  	var encodeBuf [DifficultySize]byte
   201  	d.PutBytesBE(encodeBuf[:])
   202  
   203  	var buf [DifficultySize*2 + 2]byte
   204  	buf[0] = '"'
   205  	buf[DifficultySize*2+1] = '"'
   206  	fasthex.Encode(buf[1:], encodeBuf[:])
   207  	return buf[:], nil
   208  }
   209  
   210  func MustDifficultyFromString(s string) Difficulty {
   211  	if d, err := DifficultyFromString(s); err != nil {
   212  		panic(err)
   213  	} else {
   214  		return d
   215  	}
   216  }
   217  
   218  func DifficultyFromString(s string) (Difficulty, error) {
   219  	if strings.HasPrefix(s, "0x") {
   220  		if buf, err := fasthex.DecodeString(s[2:]); err != nil {
   221  			return ZeroDifficulty, err
   222  		} else {
   223  			//TODO: check this
   224  			var d [DifficultySize]byte
   225  			copy(d[DifficultySize-len(buf):], buf)
   226  			return DifficultyFromBytes(d[:]), nil
   227  		}
   228  	} else {
   229  		if buf, err := fasthex.DecodeString(s); err != nil {
   230  			return ZeroDifficulty, err
   231  		} else {
   232  			if len(buf) != DifficultySize {
   233  				return ZeroDifficulty, errors.New("wrong difficulty size")
   234  			}
   235  
   236  			return DifficultyFromBytes(buf), nil
   237  		}
   238  	}
   239  }
   240  
   241  func DifficultyFromBytes(buf []byte) Difficulty {
   242  	return Difficulty(uint128.FromBytesBE(buf))
   243  }
   244  
   245  func NewDifficulty(lo, hi uint64) Difficulty {
   246  	return Difficulty{Lo: lo, Hi: hi}
   247  }
   248  
   249  func DifficultyFrom64(v uint64) Difficulty {
   250  	return NewDifficulty(v, 0)
   251  }
   252  
   253  func (d *Difficulty) UnmarshalJSON(b []byte) (err error) {
   254  	if len(b) == 0 {
   255  		return io.ErrUnexpectedEOF
   256  	}
   257  
   258  	if b[0] == '"' {
   259  		if len(b) < 2 || (len(b)%2) != 0 || b[len(b)-1] != '"' {
   260  			return errors.New("invalid bytes")
   261  		}
   262  
   263  		if len(b) == DifficultySize*2+2 {
   264  			// fast path
   265  			var buf [DifficultySize]byte
   266  			if _, err := fasthex.Decode(buf[:], b[1:len(b)-1]); err != nil {
   267  				return err
   268  			} else {
   269  				*d = DifficultyFromBytes(buf[:])
   270  				return nil
   271  			}
   272  		}
   273  
   274  		if diff, err := DifficultyFromString(string(b[1 : len(b)-1])); err != nil {
   275  			return err
   276  		} else {
   277  			*d = diff
   278  
   279  			return nil
   280  		}
   281  	} else {
   282  		// Difficulty as uint64
   283  		if d.Lo, err = utils.ParseUint64(b); err != nil {
   284  			// Fallback to big int if number is out of range
   285  			if errors.Is(err, strconv.ErrRange) {
   286  				var bInt big.Int
   287  				if err = bInt.UnmarshalText(b); err != nil {
   288  					return err
   289  				} else {
   290  					//recover bigint panics
   291  					defer func() {
   292  						if e := recover(); e != nil {
   293  							if err = e.(error); err == nil {
   294  								err = fmt.Errorf("panic: %v", e)
   295  							}
   296  						}
   297  					}()
   298  					*d = Difficulty(uint128.FromBig(&bInt))
   299  				}
   300  			}
   301  			return err
   302  		} else {
   303  			d.Hi = 0
   304  			return nil
   305  		}
   306  	}
   307  }
   308  
   309  func (d Difficulty) Bytes() []byte {
   310  	var buf [DifficultySize]byte
   311  	d.PutBytesBE(buf[:])
   312  	return buf[:]
   313  }
   314  
   315  func (d Difficulty) String() string {
   316  	return fasthex.EncodeToString(d.Bytes())
   317  }
   318  
   319  func (d Difficulty) StringNumeric() string {
   320  	return uint128.Uint128(d).String()
   321  }
   322  
   323  func (d *Difficulty) Scan(src any) error {
   324  	if src == nil {
   325  		return nil
   326  	} else if buf, ok := src.([]byte); ok {
   327  		if len(buf) == 0 {
   328  			return nil
   329  		}
   330  
   331  		if len(buf) != DifficultySize {
   332  			return errors.New("invalid difficulty size")
   333  		}
   334  
   335  		*d = DifficultyFromBytes(buf)
   336  
   337  		return nil
   338  	}
   339  	return errors.New("invalid type")
   340  }
   341  
   342  func (d *Difficulty) Value() (driver.Value, error) {
   343  	return d.Bytes(), nil
   344  }