Hi Guest

More contents, please log on!

Bitmere.com 区块链技术 Content
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。
代码分析
三大模块
代码还是比较简单清晰的,主要有三个模块,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()
}
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
Tags: Pow
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.
You have to log in before you can reply Login | 立即注册

Points Rules

Write the first review

蓝天天使2017 初中生
  • Follow

    0

  • Following

    0

  • Articles

    10

Promoted