2024-10-23 19:33:07 +01:00
|
|
|
package ailur_pow
|
2024-07-20 16:48:14 +01:00
|
|
|
|
|
|
|
import (
|
2024-09-29 11:15:24 +01:00
|
|
|
"bytes"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"time"
|
2024-09-22 14:56:09 +01:00
|
|
|
|
2024-09-29 11:15:24 +01:00
|
|
|
"crypto/rand"
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/hex"
|
|
|
|
|
|
|
|
"golang.org/x/crypto/argon2"
|
2024-07-20 16:48:14 +01:00
|
|
|
)
|
|
|
|
|
2024-09-29 11:15:24 +01:00
|
|
|
func PoW(difficulty uint64, resource string, wait int64) (string, error) {
|
|
|
|
for {
|
|
|
|
initialTime := time.Now().Unix()
|
|
|
|
var timestamp [8]byte
|
|
|
|
binary.LittleEndian.PutUint64(timestamp[:], uint64(initialTime))
|
|
|
|
|
|
|
|
var nonce [16]byte
|
|
|
|
_, err := rand.Read(nonce[:])
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
output := hex.EncodeToString(argon2.IDKey(nonce[:], bytes.Join([][]byte{timestamp[:], []byte(resource)}, []byte{}), 1, 64*1024, 4, 32))
|
|
|
|
var difficultyString strings.Builder
|
|
|
|
for range difficulty {
|
|
|
|
difficultyString.WriteString("0")
|
|
|
|
}
|
|
|
|
if strings.HasPrefix(output, difficultyString.String()) {
|
|
|
|
return strconv.FormatUint(difficulty, 10) + ":" + strconv.FormatInt(initialTime, 10) + ":" + hex.EncodeToString(nonce[:]) + ":" + resource + ":", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if wait > 0 {
|
|
|
|
// Wait for a while before trying again
|
|
|
|
time.Sleep(time.Duration(wait) * time.Millisecond)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func VerifyPoW(pow string) bool {
|
|
|
|
powSplit := strings.Split(pow, ":")
|
|
|
|
difficulty, err := strconv.ParseUint(powSplit[0], 10, 64)
|
2024-07-20 16:48:14 +01:00
|
|
|
if err != nil {
|
2024-09-29 11:15:24 +01:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
timestamp, err := strconv.ParseInt(powSplit[1], 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
timestampBytes := make([]byte, 8)
|
|
|
|
binary.LittleEndian.PutUint64(timestampBytes, uint64(timestamp))
|
|
|
|
nonce, err := hex.DecodeString(powSplit[2])
|
|
|
|
if err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
resource := powSplit[3]
|
|
|
|
output := hex.EncodeToString(argon2.IDKey(nonce, bytes.Join([][]byte{timestampBytes, []byte(resource)}, []byte{}), 1, 64*1024, 4, 32))
|
|
|
|
var difficultyString strings.Builder
|
|
|
|
for range difficulty {
|
|
|
|
difficultyString.WriteString("0")
|
|
|
|
}
|
|
|
|
if strings.HasPrefix(output, difficultyString.String()) {
|
|
|
|
return true
|
2024-07-20 16:48:14 +01:00
|
|
|
} else {
|
2024-09-29 11:15:24 +01:00
|
|
|
return false
|
2024-07-20 16:48:14 +01:00
|
|
|
}
|
|
|
|
}
|