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 }