consensus/types/types.go
DataHoarder 4ef60296f1
Updated to Go 1.21
* Replaced exp/slices and exp/maps with slices/maps implementation
* Replaced utils.Min/Max with min/max
* Introduced GOEXPERIMENT=loopvar on build steps
* Updated tests/docker-compose to go1.21-rc-alpine
* Updated nginx to 1.25
* Preallocate mined blocks on Sidechain
* Update edwards25519 version
2023-07-20 07:40:18 +02:00

168 lines
2.8 KiB
Go

package types
import (
"bytes"
"database/sql/driver"
"encoding/hex"
"errors"
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
"runtime"
"unsafe"
)
const HashSize = 32
type Hash [HashSize]byte
var ZeroHash Hash
func (h Hash) MarshalJSON() ([]byte, error) {
var buf [HashSize*2 + 2]byte
buf[0] = '"'
buf[HashSize*2+1] = '"'
hex.Encode(buf[1:], h[:])
return buf[:], nil
}
func MustHashFromString(s string) Hash {
if h, err := HashFromString(s); err != nil {
panic(err)
} else {
return h
}
}
func HashFromString(s string) (Hash, error) {
var h Hash
if buf, err := hex.DecodeString(s); err != nil {
return h, err
} else {
if len(buf) != HashSize {
return h, errors.New("wrong hash size")
}
copy(h[:], buf)
return h, nil
}
}
func HashFromBytes(buf []byte) (h Hash) {
if len(buf) != HashSize {
return
}
copy(h[:], buf)
return
}
// Compare consensus way of comparison
func (h Hash) Compare(other Hash) int {
//golang might free other otherwise
defer runtime.KeepAlive(other)
defer runtime.KeepAlive(h)
a := unsafe.Slice((*uint64)(unsafe.Pointer(&h)), len(h)/int(unsafe.Sizeof(uint64(0))))
b := unsafe.Slice((*uint64)(unsafe.Pointer(&other)), len(other)/int(unsafe.Sizeof(uint64(0))))
if a[3] < b[3] {
return -1
}
if a[3] > b[3] {
return 1
}
if a[2] < b[2] {
return -1
}
if a[2] > b[2] {
return 1
}
if a[1] < b[1] {
return -1
}
if a[1] > b[1] {
return 1
}
if a[0] < b[0] {
return -1
}
if a[0] > b[0] {
return 1
}
return 0
}
func (h Hash) Equals(o Hash) bool {
return bytes.Compare(h[:], o[:]) == 0
}
func (h Hash) String() string {
return hex.EncodeToString(h[:])
}
func (h *Hash) Scan(src any) error {
if src == nil {
return nil
} else if buf, ok := src.([]byte); ok {
if len(buf) == 0 {
return nil
}
if len(buf) != HashSize {
return errors.New("invalid hash size")
}
copy((*h)[:], buf)
return nil
}
return errors.New("invalid type")
}
func (h *Hash) Value() (driver.Value, error) {
if *h == ZeroHash {
return nil, nil
}
return (*h)[:], nil
}
func (h *Hash) UnmarshalJSON(b []byte) error {
if len(b) == 0 || len(b) == 2 {
return nil
}
if len(b) != HashSize*2+2 {
return errors.New("wrong hash size")
}
if _, err := hex.Decode(h[:], b[1:len(b)-1]); err != nil {
return err
} else {
return nil
}
}
type Bytes []byte
func (b Bytes) MarshalJSON() ([]byte, error) {
buf := make([]byte, len(b)*2+2)
buf[0] = '"'
buf[len(buf)-1] = '"'
hex.Encode(buf[1:], b)
return buf, nil
}
func (b Bytes) String() string {
return hex.EncodeToString(b)
}
func (b *Bytes) UnmarshalJSON(buf []byte) error {
var s string
if err := utils.UnmarshalJSON(buf, &s); err != nil {
return err
}
if buf2, err := hex.DecodeString(s); err != nil {
return err
} else {
*b = append(*b, buf2...)
return nil
}
}