pow算法的简介
pow算法的代表性应用就是比特币系统,pow算法的原义是工作量证明算法,故名思意就是干多少活的证明。其实就是暴力求值,通过暴力循环 找到一个合适的哈希值,
这篇文中由详细的介绍
package main
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"math/big"
"strconv"
"time"
)
// 定义区块链的结构
type Block struct {
LastHash string //上一区块的哈希
Hash string //本区块的哈希值
Data string //数据
TimeStamp string //时间戳
Height int //区块高度
Nonce int64 //随机数
DiffNum uint //难度值
}
// 简单的链式结构
var blockchain []Block
// 难度值
var diffNum uint = 17
// 挖矿函数即工作量证明算法
// 1.通过增大随机数的值 寻找适合的哈希值
// 2.类比比特币 寻找小于目标难度的哈希值
// 工作量证明算法的本质就是暴力求值 循环比较 直至找到符合要求的哈希值
func mine(data string) Block {
// 定义区块
if len(blockchain) < 1 {
fmt.Println("没有区块头")
}
// 获取链上的最后一个区块
lastBlock := blockchain[len(blockchain)-1]
// 定义一个新的区块
newBlock := new(Block)
newBlock.LastHash = lastBlock.Hash
newBlock.TimeStamp = time.Now().String()
newBlock.Height = lastBlock.Height + 1
newBlock.DiffNum = diffNum
newBlock.Data = data
var nonce int64 = 0
newBigInt := big.NewInt(1)
newBigInt.Lsh(newBigInt, 256-diffNum) // 相当于1 左移256-diffNum
// 暴力计算
for {
newBlock.Nonce = nonce
newBlock.getHash()
hashInt := big.Int{}
hashBytes, _ := hex.DecodeString(newBlock.Hash)
hashInt.SetBytes(hashBytes) //将区块哈希值转大数字
// 寻找合适的值
// 比较x和y的大小。x<y时返回-1;x>y时返回+1;否则返回0
if hashInt.Cmp(newBigInt) == -1 {
break
} else {
nonce++ //递增随机数 直到找到合适的哈希值
}
}
return *newBlock
}
//序列化
func (b *Block) serialize() []byte {
bytes, err := json.Marshal(b)
if err != nil {
log.Panic(err)
}
return bytes
}
// 获取本区块的哈希值
func (b *Block) getHash() {
result := sha256.Sum256(b.serialize())
b.Hash = hex.EncodeToString(result[:])
}
func main() {
// 新建一个区块头
genesisBlock := &Block{
TimeStamp: time.Now().String(),
Data: "创世区块",
LastHash: "0000000000000000000000000000000000000000000000000000000000000000",
Height: 1,
Nonce: 0,
DiffNum: 0,
}
genesisBlock.getHash()
fmt.Println(genesisBlock)
//将创世区块添加进区块链
blockchain = append(blockchain, *genesisBlock)
for i := 0; i < 10; i++ {
newBlock := mine("天气不错" + strconv.Itoa(i))
blockchain = append(blockchain, newBlock)
fmt.Println(newBlock)
}
}