为了账号安全,请及时绑定邮箱和手机立即绑定

区块链初始化与实现POW工作量证明

标签:
Go

目录:

一.初始化区块链

1.代码结构

2. 定义区块结构与方法

3. 定义区块链结构与方法

4. 帮助库代码

5. 测试生成区块与初始化区块链

6. 测试代码

二. POW挖矿实现

1.代码结构

2. 定义pow算法实现

3. 修改区块的生成方式(从自定义到挖矿)

4. 测试代码,测试挖矿

5.验证区块有效性

一.初始化区块链

1. 代码结构

Block.go :定义区块结构与方法

BlockChain.go :定义区块链结构与方法

help.go :将常用代码块进行封装,形成帮助库

main.go:测试代码

2.定义区块结构与方法

package BLC  import (    "time"    "strconv"    "bytes"    "crypto/sha256" )  //定义区块 type Block struct {    //1.区块高度,也就是区块的编号,第几个区块    Height int64    //2.上一个区块的Hash值    PreBlockHash []byte    //3.交易数据(最终都属于transaction 事务)    Data []byte    //4.创建时间的时间戳    TimeStamp int64    //5.当前区块的Hash值    Hash []byte    //6.Nonce 随机数,用于验证工作量证明    Nonce int64 }  //定义区块生成Hash的方法 func (block *Block) SetHash() {    //1.将Height 转换为字节数组 []byte    heightBytes := IntToHex(block.Height)     //2.将TimeStamp 转换为字节数组 []byte    //2.1 将Int64的TimeStamp 转换成二进制    timeString := strconv.FormatInt(block.TimeStamp, 2)    //2.2 将二进制字符串转成字节数组    timeBytes := []byte(timeString)     //3.拼接所有属性,形成一个二维的byte数组    blockBytes := bytes.Join([][]byte{heightBytes, block.PreBlockHash, block.Data, timeBytes, block.Hash}, []byte{})    //4.生成Hash    hash := sha256.Sum256(blockBytes)    block.Hash = hash[:] }  //1. 创建新的区块 func NewBlock(data string, height int64, PreBlockHash []byte) *Block {    //创建区块    block := &Block{       height,       PreBlockHash,       []byte(data),       time.Now().Unix(),       nil,       0,    }    //设置Hash    block.SetHash()    return block  }  //2.生成创世区块 func CreateGenesisBlock(data string) *Block {     return NewBlock(data, 1, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})  }

3.定义区块链与方法

package BLC  type BlockChain struct {    Blocks []*Block //存储有序的区块 }   func (blc *BlockChain)AddBlockChain(data string,height int64,preHash []byte){    //创建新区块    newBlock := NewBlock(data,height,preHash)    //往链中添加区块    blc.Blocks=append(blc.Blocks,newBlock)  }   //1.创建带有创世区块的区块链 func CreateBlockChainWithGenesisBlock() *BlockChain {     //创建创世区块    genesisBlock := CreateGenesisBlock("Genesis Data..")    //返回区块链对象    return &BlockChain{[]*Block{genesisBlock}}  }

4.帮助代码库

package BLC  import (    "bytes"    "encoding/binary"    "log" )  //将int64转换为字节数组 func IntToHex(num int64) []byte {    buff := new(bytes.Buffer)    err := binary.Write(buff, binary.BigEndian, num)    if err != nil {       log.Panic(err)    }    return buff.Bytes() }

5.测试代码

package main  import (    "publicChain/BLC"    "fmt" )  func main() {     //创建创世区块    blockChain := BLC.CreateBlockChainWithGenesisBlock()     //创建新的区块    blockChain.AddBlockChain("Send $100 to Bruce", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash)    blockChain.AddBlockChain("Send $200 to Apple", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash)    blockChain.AddBlockChain("Send $300 to Alice", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash)    blockChain.AddBlockChain("Send $400 to Bob", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash)     fmt.Printf("创建的区块链为:\t%v\n", blockChain)    fmt.Printf("区块链存储的区块为:\t%v\n", blockChain.Blocks)    fmt.Printf("第二个区块的数据信息(交易信息)为:\t%v\n", string(blockChain.Blocks[1].Data))  }

结果显示

二. POW挖矿实现

1.代码结构

多出的ProofOfWork.go用于实现挖矿

2. 定义pow算法实现

ProofOfWork.go

package BLC  import (    "math/big"    "bytes"    "crypto/sha256"    "fmt"    "time" )  type ProofOfWork struct {    Block  *Block   //当前要验证的区块    target *big.Int //大数存储,区块难度 }  //数据拼接,返回字节数组 func (pow *ProofOfWork) prePareData(nonce int) []byte {     data := bytes.Join(       [][]byte{          pow.Block.PreBlockHash,          pow.Block.Data,          IntToHex(pow.Block.TimeStamp),          IntToHex(int64(targetBit)),          IntToHex(int64(nonce)),          IntToHex(int64(pow.Block.Height)),       },       []byte{},    )    return data }  //256位Hash里面至少要有16个零0000 0000 0000 0000 const targetBit = 16  func (proofOfWork *ProofOfWork) Run(num int64) ([]byte, int64) {     //3.判断Hash的有效性,如果满足条件循环体     nonce := 0    var hashInt big.Int //存储新生成的hash值    var hash [32]byte     for {       //1. 将Block的属性拼接成字节数组       databytes := proofOfWork.prePareData(nonce)        //2.生成Hash       hash = sha256.Sum256(databytes)       fmt.Printf("挖矿中..%x\n", hash)       //3. 将hash存储至hashInt       hashInt.SetBytes(hash[:])         //4.判断hashInt是否小于Block里面的target       // Cmp compares x and y and returns:       //       //   -1 if x <  y       //    0 if x == y       //   +1 if x >  y       //需要hashInt(y)小于设置的target(x)       if proofOfWork.target.Cmp(&hashInt) == 1 {          //fmt.Println("挖矿成功", hashInt)          fmt.Printf("第%d个区块,挖矿成功:%x\n",num,hash)          fmt.Println(time.Now())          time.Sleep(time.Second * 2)          break        }        nonce ++     }     return hash[:], int64(nonce)  }  //创建新的工作量证明对象 func NewProofOfWork(block *Block) *ProofOfWork {    /*1.创建初始值为1的target    0000 0001    8 - 2    */     target := big.NewInt(1)     //2.左移256-targetBit    target = target.Lsh(target, 256-targetBit)     return &ProofOfWork{block, target} }

3. 修改区块的生成方式(从自定义到挖矿)

Block.go

package BLC  import (    "time" )  //定义区块 type Block struct {    //1.区块高度,也就是区块的编号,第几个区块    Height int64    //2.上一个区块的Hash值    PreBlockHash []byte    //3.交易数据(最终都属于transaction 事务)    Data []byte    //4.创建时间的时间戳    TimeStamp int64    //5.当前区块的Hash值    Hash []byte    //6.Nonce 随机数,用于验证工作量证明    Nonce int64 }  //1. 创建新的区块 func NewBlock(data string, height int64, PreBlockHash []byte) *Block {    //创建区块    block := &Block{       height,       PreBlockHash,       []byte(data),       time.Now().Unix(),       nil,       0,    }    //调用工作量证明的方法,并且返回有效的Hash和Nonce值    //创建pow对象    pow := NewProofOfWork(block)    //挖矿验证    hash, nonce := pow.Run(height)     block.Hash = hash[:]    block.Nonce = nonce    return block  }  //2.生成创世区块 func CreateGenesisBlock(data string) *Block {     return NewBlock(data, 1, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})  }

4. 测试代码,测试挖矿

main.go

package main  import (    "publicChain/part2-工作量证明/BLC"    "fmt" )  func main() {     fmt.Println("开始挖矿")    //创建创世区块    blockChain := BLC.CreateBlockChainWithGenesisBlock()     //创建新的区块    blockChain.AddBlockChain("Send $100 to Bruce", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash)     blockChain.AddBlockChain("Send $200 to Apple", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash)     blockChain.AddBlockChain("Send $300 to Alice", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash)     blockChain.AddBlockChain("Send $400 to Bob", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash)     fmt.Printf("创建的区块链为:\t%v\n", blockChain)    fmt.Printf("区块链存储的区块为:\t%v\n", blockChain.Blocks)    fmt.Printf("第二个区块的数据信息(交易信息)为:\t%v\n", string(blockChain.Blocks[1].Data))    fmt.Printf("第二个区块的随机数为:\t%v\n", blockChain.Blocks[1].Nonce)  }

测试结果

共计对五个区块进行挖矿,结果如上

5.验证区块有效性 

ProofOfWork.go

//判断挖矿得到的区块是否有效 func (proofOfWork *ProofOfWork) IsValid() bool {    //1.proofOfWork.Block.Hash    //2.proofOfWork.Target    var hashInt big.Int     hashInt.SetBytes(proofOfWork.Block.Hash)     if proofOfWork.target.Cmp(&hashInt) == 1 {       return true    }    return false }

测试代码:

main.go

//通过POW挖出新的区块block block := BLC.NewBlock("Send $500 to Tom", blockChain.Blocks[len(blockChain.Blocks)-1].Height+1, blockChain.Blocks[len(blockChain.Blocks)-1].Hash) //手动将该区块添加至区块链中 blockChain.Blocks = append(blockChain.Blocks, block) //创建一个工作量证明对象 proofOfWork := BLC.NewProofOfWork(block) //判断该区块是否合法有效 fmt.Println(proofOfWork.IsValid())

测试结果:

第六个区块是我们新创建的区块,返回值为true,验证有效

参考资料:

区块链共识算法-POW: https://www.jianshu.com/p/b23cbafbbad2 

©著作权归作者所有:来自51CTO博客作者暗黑魔君的原创作品,如需转载,请与作者联系,否则将追究法律责任


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消