47 lines
1.3 KiB
Go
47 lines
1.3 KiB
Go
package pow
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"math"
|
|
"strconv"
|
|
|
|
"github.com/tendermint/tendermint/crypto"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
)
|
|
|
|
// generate the mine message
|
|
func GenerateMsgMine(sender sdk.AccAddress, count uint64, difficulty uint64) MsgMine {
|
|
nonce, hash := mine(sender, count, difficulty)
|
|
return NewMsgMine(sender, difficulty, count, nonce, hash)
|
|
}
|
|
|
|
func hash(sender sdk.AccAddress, count uint64, nonce uint64) []byte {
|
|
var bytes []byte
|
|
bytes = append(bytes, []byte(sender)...)
|
|
countBytes := strconv.FormatUint(count, 16)
|
|
bytes = append(bytes, countBytes...)
|
|
nonceBytes := strconv.FormatUint(nonce, 16)
|
|
bytes = append(bytes, nonceBytes...)
|
|
hash := crypto.Sha256(bytes)
|
|
// uint64, so we just use the first 8 bytes of the hash
|
|
// this limits the range of possible difficulty values (as compared to uint256), but fine for proof-of-concept
|
|
ret := make([]byte, hex.EncodedLen(len(hash)))
|
|
hex.Encode(ret, hash)
|
|
return ret[:16]
|
|
}
|
|
|
|
func mine(sender sdk.AccAddress, count uint64, difficulty uint64) (uint64, []byte) {
|
|
target := math.MaxUint64 / difficulty
|
|
for nonce := uint64(0); ; nonce++ {
|
|
hash := hash(sender, count, nonce)
|
|
hashuint, err := strconv.ParseUint(string(hash), 16, 64)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if hashuint < target {
|
|
return nonce, hash
|
|
}
|
|
}
|
|
}
|