package core
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
)
|
|
|
|
// Hash is the type for a hash data packet
|
|
type Hash [32]byte
|
|
|
|
// IsZero returns true if the Hash is empty (all zeroes)
|
|
func (h *Hash) IsZero() bool {
|
|
z := Hash{}
|
|
if bytes.Equal(z[:], h[:]) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
func (h *Hash) String() string {
|
|
return hex.EncodeToString(h[:])
|
|
}
|
|
|
|
// HashBytes performs a hash over a given byte array
|
|
func HashBytes(b []byte) Hash {
|
|
h := sha256.Sum256(b)
|
|
return h
|
|
}
|
|
|
|
// PoWData is the interface for the data that have the Nonce parameter to calculate the Proof-of-Work
|
|
type PoWData interface {
|
|
Bytes() []byte
|
|
GetNonce() uint64
|
|
IncrementNonce()
|
|
}
|
|
|
|
// CheckPoW verifies the PoW difficulty of a Hash
|
|
func CheckPoW(hash Hash, difficulty uint64) bool {
|
|
var empty [32]byte
|
|
if !bytes.Equal(hash[:][0:difficulty], empty[0:difficulty]) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// CalculatePoW calculates the nonce for the given data in order to fit in the current Proof of Work difficulty
|
|
func CalculatePoW(data PoWData, difficulty uint64) (uint64, error) {
|
|
hash := HashBytes(data.Bytes())
|
|
for !CheckPoW(hash, difficulty) {
|
|
data.IncrementNonce()
|
|
|
|
hash = HashBytes(data.Bytes())
|
|
}
|
|
return data.GetNonce(), nil
|
|
}
|
|
|
|
func Uint64ToBytes(u uint64) []byte {
|
|
buff := new(bytes.Buffer)
|
|
err := binary.Write(buff, binary.LittleEndian, u)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return buff.Bytes()
|
|
|
|
}
|
|
|
|
func Uint64FromBytes(b []byte) uint64 {
|
|
return binary.LittleEndian.Uint64(b)
|
|
}
|