forked from Wasakachain/Miner
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblock.go
111 lines (97 loc) · 2.64 KB
/
block.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package main
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"sync"
"time"
)
//Block represents a block candidate
type Block struct {
index uint32
transactionsIncluded uint32
difficulty uint32
expectedReward string
rewardAddress string
blockDataHash string
dateCreated string
nonce uint64
mined bool
}
func (b *Block) mine(host string, mutex *sync.Mutex, once *sync.Once) {
for !b.mined {
if block, ok := validProof(*b); ok {
b.mined = true
once.Do(func() {
SubmitBlock(block, host)
})
return
}
mutex.Lock()
b.nonce++
b.dateCreated = time.Now().UTC().Format(time.RFC3339)
mutex.Unlock()
}
}
//Hash returns a sha256 hash string of the block data
func (b *Block) Hash() string {
json, _ := json.Marshal(map[string]interface{}{
"blockDataHash": b.blockDataHash,
"dateCreated": b.dateCreated,
"nonce": strconv.Itoa(int(b.nonce)),
})
hasher := sha256.New()
hasher.Write(json)
return hex.EncodeToString(hasher.Sum(nil))
}
func validProof(b Block) (Block, bool) {
return b, strings.Repeat("0", int(b.difficulty)) == string(b.Hash()[:b.difficulty])
}
//SubmitBlock send the mined block to the node
func SubmitBlock(b Block, host string) {
data, _ := json.Marshal(map[string]interface{}{
"blockDataHash": b.blockDataHash,
"dateCreated": b.dateCreated,
"blockHash": b.Hash(),
"nonce": strconv.Itoa(int(b.nonce)),
})
resp, err := http.Post(host+"/mining/submit-mined-block", "application/json",
bytes.NewBuffer(data))
if err != nil {
println(err.Error())
return
}
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
for key, message := range result {
var color string
if key == "errorMsg" {
color = "\033[41m"
} else {
color = "\033[42m"
}
fmt.Printf("%vResult: %v\033[0m\n", color, message)
}
}
func requestBlock(host string) (Block, error) {
resp, err := http.Get(fmt.Sprintf("%s/mining/get-mining-job/%s", host, account["address"]))
if err != nil {
return Block{}, err
}
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
return Block{
index: uint32(result["index"].(float64)),
transactionsIncluded: uint32(result["transactionsIncluded"].(float64)),
difficulty: uint32(result["difficulty"].(float64)),
expectedReward: result["expectedReward"].(string),
rewardAddress: result["rewardAddress"].(string),
blockDataHash: result["blockDataHash"].(string),
dateCreated: time.Now().UTC().Format(time.RFC3339),
}, nil
}