First, the principle of mining
Block header information analysis (a) area
data analysis | purpose | Updated | size |
---|---|---|---|
Version version | Regional version number | After updating the software, assign a new version number | 4 |
Previous hashPrevBlock block HASH | 256 HASH value of the previous block | When the new block to come | 32 |
HASH value hashMerkleRoot Merkel root | Based on 256 HASH value of a block of all transactions | Accept a deal | 32 |
Time timestamp | 1970-01-01 00:00 UTC from the beginning to now, in seconds timestamp | Is updated every few seconds | 4 |
Bits current target value HASH | Compression format of the current value of the target of the HASH | When mining difficulty adjustment | 4 |
Random number Nonce | From 0 to 32-bit random | When generating HASH A (HASH generates a random number every time you want to grow) | 4 |
(B) the nature of mining
- Is PoW mining algorithm (workload proof mechanism) Bitcoin consensus mechanisms
- The nature of mining is to calculate a hash value
- Mining process is repeated Hash value calculation block header region, a Nonce continue to modify the random number, until the Hash value is less than the target bits difficulty even if the computed hash mining successful
- the header area of six information calculation cycle patchwork Hash value
- for that loop Nonce from 0 to the maximum value of int (about 4 billion). Nonce time stamp and changes worth, calculates a value of 0 is high. Because the target is a Hash value 0 at the beginning of a plurality of 64-bit numbers. The more high digits 0, then the likelihood is less than the target of the greater difficulty of Hash. When less than, that successful mining.
- bits smaller the value, the more high 0 Hash target value, which results in each node to be carried out to calculate the number of billion times, it can be found to meet the conditions of Hash, in short, the smaller the bits value, the greater the difficulty
- credits will adjust the target bit Hash value, in order to control difficult.
And the difficulty of computing the target Bitcoin bits trends
Target computational difficulty illustrated
A Case Study of blocks 516 532
- = Bits "0x17502ab7"
- 16 bits are used to store certain difficulty hexadecimal value - coefficient coefficient, coeffcient = 0x502ab7
- exponent index, exponent = 0x17
- target = confficient * Math.pow(2,8*(exponent - 3))
Step quick calculation of difficult targets
- The difficulty of obtaining a target factor
- Difficulty in obtaining objective indices
- Calculation of high fill 0
- Low computing fill 0
- Calculating a target value
We usually read and write, according to the habit of doing from the right to the left is a large number, the right is the decimal. The computer data storage mode is small head rank storage mode, i.e. low front, high after. Therefore, the block data recorded in the file header bits are arranged in order of small data. Thus, when parsing a hexadecimal value to be calculated after carrying out the bulk of the bit sequence and the bit sequence rearranged head.
- After two hash256 algorithm
- Will be reversed end hex size
GO achieve three blocks chain PoW algorithm
package main
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"math/big"
"strconv"
"strings"
"time"
)
func main() {
CheckMiningResult()
}
//验证挖矿结果
func CheckMiningResult() {
//初始化区块头信息
var strVersion,strPre_hash,strMerkle_root,strTimeStamp,strBits,strNonce string
strVersion = "20000000"
strPre_hash = "0000000000000000002805302293df911371f53a595b2cb571c2536ceef62e60"
strMerkle_root = "2ce0a3d3ed22dfd8ab342f5692a51e4b3a2d7778ac0e12f75fe856c59890a8a9"
currenttime := "2018-04-26 18:40:17"
bits := 390680589
nonce := 3778663653
strTimeStamp = DataToTimeHexStr(currenttime)
fmt.Println("strTimeStamp",strTimeStamp)
strBits = strconv.FormatInt(int64(bits),16)
fmt.Println("strBits",strBits)
strNonce = strconv.FormatInt(int64(nonce),16)
fmt.Println("strNonce",strNonce)
//计算挖矿难度目标hash
targetHash := GetTargetHash(strBits)
fmt.Println("目标hash",targetHash)
//计算实际挖矿hash
miningHash := GetMiningHash(strVersion,strPre_hash,strMerkle_root,strTimeStamp,strNonce,strBits)
fmt.Println("实际hash",miningHash)
//比较hash大小
flag := CompareHash(miningHash,targetHash)
fmt.Println("挖矿结果",flag)
}
//计算挖矿目标的hash
func GetTargetHash(bits string) string {
//1. 获取目标难度中的系数
coefficient := bits[2:]
//2. 获取目标难度中的指数
exponent := bits[:2]
exp,_ := strconv.ParseInt(exponent,16,0)
//3. 计算高位补0
prefix := strings.Repeat("0",64 - int(exp) * 2)
//4. 计算低位补0
suffix := strings.Repeat("0",64-len(prefix) - 6)
//5. 计算目标数值
strTargetHash := prefix + coefficient + suffix
return strTargetHash
}
//计算实际挖矿的hash
func GetMiningHash(strVersion,strPre_hash,strMerkle_root,strTimeStamp,strBits,strNonce string) string {
//获取区块头中六个参数的十六进制数,转换成小头位序排列方式
_, version := ReverseHexString(strVersion)
_, pre_hash := ReverseHexString(strPre_hash)
_, merkle_root := ReverseHexString(strMerkle_root)
_, timeStamp := ReverseHexString(strTimeStamp)
_, bits := ReverseHexString(strBits)
_, nonce := ReverseHexString(strNonce)
//将6个小头位序的数值拼接,形成区块头信息字符串
header_hex := version + pre_hash + merkle_root + timeStamp + bits + nonce
//将区块头信息经过两次hash256算法
hashedStr := SHA256DOUSTR(header_hex,true)
//将十六进制字符串进行大小端颠倒
_,res := ReverseHexString(hashedStr)
return res
}
//比较目标hash与挖矿hash的大小
func CompareHash(stringMiningHash,strTargetHash string) bool {
var miningHash big.Int
var targetHash big.Int
miningHash.SetString(stringMiningHash,16)
targetHash.SetString(strTargetHash,16)
result := new(big.Int)
result.Sub(&miningHash,&targetHash)
value := fmt.Sprintf("%+d",result)
if strings.HasPrefix(value,"-") {
return true
} else if strings.HasPrefix(value,"+0"){
return true
} else {
return false
}
}
//将16进制进行大小端颠倒
func ReverseHexString(hexString string) ([]byte,string) {
data,_ := hex.DecodeString(hexString)
for i,j := 0,len(data) - 1;i < j;i,j = i + 1,j - 1 {
data[i],data[j] = data[j],data[i]
}
return data,fmt.Sprintf("%x",data)
}
func SHA256DOUSTR(text string,ishex bool)string {
a := SHA256double(text,ishex)
return fmt.Sprintf("%x",a)
}
func ReverseByte(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]
//fmt.Println(i,j)
//break
}
}
func DateToTimeStamp(_data string) int64 {
base_data := "2006-01-02 15:04:05"
t,_ := time.Parse(base_data,_data)
tm := t.Unix()
return tm
}
func DataToTimeHexStr(_data string) string {
timeStampInt := DateToTimeStamp(_data)
strTimeStamp := strconv.FormatInt(int64(timeStampInt),16)
return strTimeStamp
}
func SHA256double(text string,ishex bool) []byte {
hashInstance := sha256.New()
if ishex {
arr,_ := hex.DecodeString(text)
hashInstance.Write(arr)
}else {
hashInstance.Write([]byte(text))
}
bytes := hashInstance.Sum(nil)
hashInstance.Reset()
hashInstance.Write(bytes)
bytes = hashInstance.Sum(nil)
return bytes
}