-
Notifications
You must be signed in to change notification settings - Fork 0
/
proofOfWork.go
72 lines (57 loc) · 1.35 KB
/
proofOfWork.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package kcoin
import (
"bytes"
"crypto/sha256"
"errors"
"math"
"math/big"
)
const targetBits = 24
const hashBits = 256
type ProofOfWork struct {
block *Block
target *big.Int
}
func NewProofOfWork(block *Block) *ProofOfWork {
target := big.NewInt(1).Lsh(
big.NewInt(1), uint(hashBits-targetBits))
return &ProofOfWork{
block: block,
target: target,
}
}
func (proofOfWork *ProofOfWork) prepareData(nonce int64) []byte {
data := bytes.Join(
[][]byte{
proofOfWork.block.PrevBlockHash,
proofOfWork.block.HashTransactions(),
IntToBytes(proofOfWork.block.Timestamp),
IntToBytes(int64(targetBits)),
IntToBytes(nonce),
}, []byte{})
return data
}
func (proofOfWork *ProofOfWork) Mine() (int64, []byte, error) {
var nonce int64
for nonce = 0; nonce < math.MaxInt64; nonce++ {
data := proofOfWork.prepareData(nonce)
hash := sha256.Sum256(data)
if isHashValid(hash[:], proofOfWork.target) {
return nonce, hash[:], nil
}
}
return nonce, []byte{}, errors.New("Can't Mine")
}
func (proofOfWork *ProofOfWork) Validate() bool {
data := proofOfWork.prepareData(proofOfWork.block.Nonce)
hash := sha256.Sum256(data)
return isHashValid(hash[:], proofOfWork.target)
}
func isHashValid(hash []byte, target *big.Int) bool {
var hashInt big.Int
hashInt.SetBytes(hash)
if hashInt.Cmp(target) == -1 {
return true
}
return false
}