目录:
一.初始化区块链
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
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。