区块链初始化与实现POW工作量证明
一.初始化区块链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.gopackage 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
- 区块链初始化与实现POW工作量证明
- 创建区块链之v2实现pow(ProofOfWork工作量证明)
- 兄弟连区块链入门教程分享区块链POW证明代码实现demo
- 给自己的区块链添加POW-工作量证明
- 任何国家都无法限制数字货币。为什么呢? 要想明白这个问题需要具备一点区块链的基础知识: 区块链使用的大致技术包括以下几种: a.点对点网络设计 b.加密技术应用 c.分布式算法的实现 d.数据存储技术 e.拜占庭算法 f.权益证明POW,POS,DPOS 原因一: 点对点网络设计 其中点对点的P2P网络是bittorent ,由于是点对点的网络,没有中心化,因此在全球分布式的网
- 任何国家都无法限制数字货币。为什么呢? 要想明白这个问题需要具备一点区块链的基础知识: 区块链使用的大致技术包括以下几种: a.点对点网络设计 b.加密技术应用 c.分布式算法的实现 d.数据存储技术 e.拜占庭算法 f.权益证明POW,POS,DPOS 原因一: 点对点网络设计 其中点对点的P2P网络是bittorent ,由于是点对点的网络,没有中心化,因此在全球分布式的网
- 比特币和区块链之:什么是工作量证明?
- 揭秘比特币和区块链(二):什么是工作量证明?
- 区块链在中国(4):比特币的工作量证明
- 基于Java语言构建区块链(二)—— 工作量证明
- 区块链,工作证明(POW)代码+原理 golang版剖析
- 从“工作量证明”解密“区块链”
- 共识机制——工作量证明POW
- 区块链,工作证明(POW)代码+原理 golang版剖析
- 用 Go 构建一个区块链 -- Part 2: 工作量证明
- DPOS委托权益证明 vs POW工作量证明
- 20181117--深入浅出区块链工作量证明
- 区块链简史(二):一篇文章看懂比特币工作量证明和矿工存在意义
- 区块链的共识机制之工作量证明机制
- [译]用go进行区块链开发2:工作量证明