简单区块链的实现(带POW挖矿系统)
蓝天天使2017
post on 2022-12-7 11:38:58
43
0
0
代码分析
三大模块
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
运行流程
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。
有了大概的运行流程接下来再来看代码就会轻松很多了。
package main
import (
"math/big"
"bytes"
"encoding/binary"
"crypto/sha256"
"fmt"
"time"
)
//Block模块
type Block struct {
Version uint64 //版本号
MerkelRoot []byte //这是一个默克尔数,这里先默认为空
TimeStamp string //时间戳
Difficulty uint64 //难度值
Nonce uint64 //挖矿所找到的随机数
PrevBlockHash []byte//前区块哈希值
Data []byte //插入的数据
Hash []byte //当前区块哈希值
}
//给到一个创建新区块的方法
func newBlock(data,prehash []byte)*Block {
block:=Block{
Version:00,
MerkelRoot:[]byte{},
TimeStamp:time.Now().Format("2006-15:04:05"),
Difficulty:difficulty,
Data:data,
PrevBlockHash:prehash,
}
//需要被挖矿之后才能创建区块,所以调用挖矿函数
pow:=NewPOW(&block)
nonce,hash:=pow.Mine()
//挖矿结束,得到哈希碰撞值
block.Nonce=nonce
block.Hash=hash
return &block
}
//Blockchain模块
const gnnesinfo="1996年9月2日,一代伟人诞生了"
//给到一个区块链结构
type Blockchain struct {
blocks []*Block
}
//将创世区块加入区块链,并返回一条可供操作的区块链
func NewblockChain()*Blockchain {
var bc Blockchain
block:=newBlock([]byte(gnnesinfo),[]byte{})
bc.blocks=append(bc.blocks,block)
return &bc
}
//给到一个增加区块的方法
func (this *Blockchain)Addblock(data []byte) {
lastblockhash:=this.blocks[len(this.blocks)-1].Hash
block:=newBlock(data,lastblockhash)
this.blocks=append(this.blocks,block)
}
//遍历,打印所有
func (this *Blockchain)PrintAll() {
for i,v:=range this.blocks {
fmt.Printf("=========区块高度%d=========\n",i)
fmt.Printf("Version : %d\n", v.Version)
fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
fmt.Printf("Hash : %x\n", v.Hash)
fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)
fmt.Printf("TimeStamp : %s\n", v.TimeStamp)
fmt.Printf("Difficuty : %d\n", v.Difficulty)
fmt.Printf("Nonce : %d\n", v.Nonce)
fmt.Printf("Data : %s\n", v.Data)
}
}
//pow挖矿模块
const difficulty=24
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
type ProofOfWork struct {
target *big.Int
block *Block
}
//给到一个根据难度值得到哈希碰撞目标值的函数
func Gettargetint()*big.Int {
targetint:=big.NewInt(1)
targetint.Lsh(targetint,256-difficulty)
return targetint
}
//创建挖矿的方法
func NewPOW(block *Block)*ProofOfWork {
var this ProofOfWork
this.block=block
targetint:=Gettargetint()
this.target=targetint
return &this
}
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化
func uint2byte(num uint64)[]byte {
var buff bytes.Buffer
binary.Write(&buff,binary.BigEndian,&num)
return buff.Bytes()
}
//挖矿的准备工作,将其他字符组合起来之后求其哈希值
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
info:=[][]byte{
pow.block.PrevBlockHash,
pow.block.Data,
uint2byte(nonce),
uint2byte(pow.block.Version),
uint2byte(pow.block.Difficulty),
[]byte(pow.block.TimeStamp),
pow.block.MerkelRoot,
}
allinfo:=bytes.Join(info,[]byte{})
hash:=sha256.Sum256(allinfo)
return hash[:]
}
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值
func (pow *ProofOfWork)Mine()(uint64,[]byte) {
var nonce uint64
//nonce从0开始穷举,直到出现哈希值小于给到的目标值
var hash []byte
for {
hash=pow.PreparetoMine(nonce)
var hashint big.Int
hashint.SetBytes(hash)
//对比哈希值是否小于目标值,小于则成功退出
if hashint.Cmp(pow.target)==-1 {
break
}
//不小于则继续穷举
nonce++
}
return nonce,hash
}
//调用
func main() {
bc:=NewblockChain()
bc.Addblock([]byte("welcometo"))
bc.Addblock([]byte("mycsdnblog"))
bc.PrintAll()
}
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
BitMere.com is Information release platform,just provides information storage space services.
The opinions expressed are solely those of the author,Does not constitute advice, please treat with caution.
The opinions expressed are solely those of the author,Does not constitute advice, please treat with caution.
You may like
Write the first review