"Block chain Collection" PoW algorithm, mining bitcoin mining verification principle and achieve GO

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
  1. Is PoW mining algorithm (workload proof mechanism) Bitcoin consensus mechanisms
  2. The nature of mining is to calculate a hash value
  3. 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

  1. = Bits "0x17502ab7"
    - 16 bits are used to store certain difficulty hexadecimal value
  2. coefficient coefficient, coeffcient = 0x502ab7
  3. exponent index, exponent = 0x17
  4. target = confficient * Math.pow(2,8*(exponent - 3))
Step quick calculation of difficult targets
  1. The difficulty of obtaining a target factor
  2. Difficulty in obtaining objective indices
  3. Calculation of high fill 0
  4. Low computing fill 0
  5. 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
}

Here Insert Picture Description

Published 24 original articles · won praise 97 · views 3520

Guess you like

Origin blog.csdn.net/qq_45828877/article/details/104488882