go语言渐入佳境[46]-区块链-比特币真实挖矿过程实现

比特币真实挖矿过程实现

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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package main

import (
"bytes"
"encoding/binary"
"log"
"fmt"
"encoding/hex"
"crypto/sha256"
"strconv"
"math"
"math/big"
)

var (

maxnonce int32 = math.MaxInt32
)

type Block struct{
version int32
prevBlockHash []byte
merkleroot [] byte
hash []byte
time int32
bits int32
nonce int32

}



//将类型转化为了字节数组
func IntToHex(num int32) []byte{
buff := new(bytes.Buffer)
//binary.LittleEndian 小端模式
err:= binary.Write(buff,binary.LittleEndian,num)

if err!=nil{
log.Panic(err)
}

return buff.Bytes()

}


//将类型转化为了字节数组
func IntToHex2(num int32) []byte{
buff := new(bytes.Buffer)
//binary.LittleEndian 小端模式
err:= binary.Write(buff,binary.BigEndian,num)

if err!=nil{
log.Panic(err)
}

return buff.Bytes()

}
//字节反转
func ReverseBytes4(data []byte){
for i,j :=0,len(data) - 1;i<j;i,j = i+1,j - 1{
data[i],data[j] = data[j],data[i]
}
}
//序列化
func (block *Block) serialize() []byte{


result := bytes.Join(
[][]byte{
IntToHex(block.version),
block.prevBlockHash,
block.merkleroot,
IntToHex(block.time),
IntToHex(block.bits),
IntToHex(block.nonce)},
[]byte{},
)

return result

}



func main(){


//前一个区块的hash
prev,_ := hex.DecodeString("000000000000000016145aa12fa7e81a304c38aec3d7c5208f1d33b587f966a6")
ReverseBytes4(prev)
fmt.Printf("%x\n",prev)

//默克尔根
merkleroot,_ := hex.DecodeString("3a4f410269fcc4c7885770bc8841ce6781f15dd304ae5d2770fc93a21dbd70d7")
ReverseBytes4(merkleroot)
fmt.Printf("%x\n",merkleroot)

//初始化区块
block := &Block{
2,
prev,
merkleroot,
[]byte{},
1418755780,
404454260,
0,
}


//目标hash
//fmt.Printf("targethash:%x",CalculateTargetFast(IntToHex2(block.bits)))
targetHash:=CalculateTargetFast(IntToHex2(block.bits))

//目标hash转换为bit.int
var tartget big.Int
tartget.SetBytes(targetHash)

//当前hash
var currenthash big.Int


//一直计算到最大值, block.nonce的值不断变化
for block.nonce < maxnonce{


//序列化,block.nonce的值不断变化带来序列化的变化
data:= block.serialize()
//double hash
fitstHash := sha256.Sum256(data)
secondhash := sha256.Sum256(fitstHash[:])

//反转
ReverseBytes4(secondhash[:])
fmt.Printf("nonce:%d, currenthash:%x\n",block.nonce,secondhash)
currenthash.SetBytes(secondhash[:])
//比较
if currenthash.Cmp(&tartget) == -1{
break
}else{
block.nonce++
}
}

}


//18 1B7B74

//计算困难度
func CalculateTargetFast(bits []byte) []byte{

var result []byte
//第一个字节 计算指数
exponent := bits[:1]
fmt.Printf("%x\n",exponent)

//计算后面3个系数
coeffient:= bits[1:]
fmt.Printf("%x\n",coeffient)


//将字节,他的16进制为"18" 转化为了string "18"
str:= hex.EncodeToString(exponent) //"18"
fmt.Printf("str=%s\n",str)
//将字符串18转化为了10进制int64 24
exp,_:=strconv.ParseInt(str,16,8)

fmt.Printf("exp=%d\n",exp)
//拼接,计算出目标hash
result = append(bytes.Repeat([]byte{0x00},32-int(exp)),coeffient...)
result = append(result,bytes.Repeat([]byte{0x00},32-len(result))...)


return result
}