简单区块链的实现(带POW挖矿系统)
蓝天天使2017
发表于 2022-12-7 11:38:58
237
0
0
代码分析" J t) Q" H! F; } ?
三大模块# W0 P% o8 X! u, M
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
运行流程
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。
有了大概的运行流程接下来再来看代码就会轻松很多了。& O$ S w c" z& Q" @" @4 ~' u
package main7 t I0 {7 P- H, [$ e; N
import (
"math/big"
"bytes"
"encoding/binary"
"crypto/sha256"
"fmt"
"time"
)
//Block模块
type Block struct {
Version uint64 //版本号
MerkelRoot []byte //这是一个默克尔数,这里先默认为空2 y" W/ X, K9 u/ r( i. L
TimeStamp string //时间戳3 A. F( E) W4 ]2 j1 y) ~7 H% `: p
Difficulty uint64 //难度值
Nonce uint64 //挖矿所找到的随机数1 P; N6 ]! J2 m! w% Y
PrevBlockHash []byte//前区块哈希值
Data []byte //插入的数据
Hash []byte //当前区块哈希值
}( c$ W( }, b' g( I3 O* n' b
//给到一个创建新区块的方法
func newBlock(data,prehash []byte)*Block {, t% ]1 p0 O# @) f; i! I
block:=Block{
Version:00,
MerkelRoot:[]byte{},
TimeStamp:time.Now().Format("2006-15:04:05"),
Difficulty:difficulty,
Data:data,
PrevBlockHash:prehash,
}
//需要被挖矿之后才能创建区块,所以调用挖矿函数! e# t5 Z: O; F* L
pow:=NewPOW(&block)
nonce,hash:=pow.Mine(). X9 ~+ f& k" E3 s
//挖矿结束,得到哈希碰撞值
block.Nonce=nonce
block.Hash=hash5 D$ ^2 \6 N5 _& F9 o
return &block, U$ W: w3 t. y! x
}
//Blockchain模块
const gnnesinfo="1996年9月2日,一代伟人诞生了" 3 Z$ ^5 X/ U8 l( S" C% n
//给到一个区块链结构; y0 b2 G6 ?- |% J2 Y# j- t3 n
type Blockchain struct {' y6 ^2 {8 m4 D
blocks []*Block
}
//将创世区块加入区块链,并返回一条可供操作的区块链
func NewblockChain()*Blockchain {* l" x2 w* \8 J# v
var bc Blockchain) R' H' a z8 g& S
block:=newBlock([]byte(gnnesinfo),[]byte{})% b7 e3 _4 V/ @; o2 ]/ [
bc.blocks=append(bc.blocks,block)1 M* c$ \& x c: p
return &bc
}
//给到一个增加区块的方法* `1 I+ @. c! ^% l
func (this *Blockchain)Addblock(data []byte) {
lastblockhash:=this.blocks[len(this.blocks)-1].Hash
block:=newBlock(data,lastblockhash)
this.blocks=append(this.blocks,block)# r g- [/ |2 [4 G8 C% e
}
//遍历,打印所有
func (this *Blockchain)PrintAll() {9 m' _- J. Y O2 M7 @
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)" W4 P5 e% u# ~1 {5 G
fmt.Printf("Difficuty : %d\n", v.Difficulty)
fmt.Printf("Nonce : %d\n", v.Nonce)
fmt.Printf("Data : %s\n", v.Data)) q* m B* ^! g+ X; Z- Z
}
}
//pow挖矿模块" d5 } A: o. w5 R% @' C% u
const difficulty=24
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字( b3 A/ k& F1 a, s
type ProofOfWork struct {
target *big.Int
block *Block8 G% \4 g I1 O; g# Y. g& M& P
}
//给到一个根据难度值得到哈希碰撞目标值的函数- ]2 S! E/ z/ U: @( z
func Gettargetint()*big.Int {- h$ h# C6 w; k
targetint:=big.NewInt(1)3 p' l0 l4 A8 A8 E# f
targetint.Lsh(targetint,256-difficulty)
return targetint- [$ d, n+ j2 E$ m
}
//创建挖矿的方法
func NewPOW(block *Block)*ProofOfWork {) `9 O5 f4 ?3 T1 q+ q1 Q+ L' \
var this ProofOfWork5 d4 M$ ?& @6 b' |8 k$ q9 ~
this.block=block) B. Q7 A0 i' V. g
targetint:=Gettargetint() y( ^* E! l6 Z2 w1 V* V
this.target=targetint
return &this9 { U$ ?- N& g* [3 y
}6 L1 v1 L9 |2 L4 `: g3 P/ J
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化
func uint2byte(num uint64)[]byte {
var buff bytes.Buffer
binary.Write(&buff,binary.BigEndian,&num)
return buff.Bytes()' c3 B' `5 ~' M5 q5 e
}+ |1 W; E1 c4 F3 m8 N% `
//挖矿的准备工作,将其他字符组合起来之后求其哈希值
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
info:=[][]byte{9 M5 Y/ Y8 V. f/ u5 ^! f
pow.block.PrevBlockHash,8 i7 M# W( d: c7 Y1 L3 J+ }8 ~
pow.block.Data,
uint2byte(nonce)," \+ _' @* e. z6 t8 K" ~
uint2byte(pow.block.Version),3 ]/ L: P! E: U, \
uint2byte(pow.block.Difficulty),
[]byte(pow.block.TimeStamp),
pow.block.MerkelRoot,
}
allinfo:=bytes.Join(info,[]byte{})
hash:=sha256.Sum256(allinfo); O; G! O) G% v4 C
return hash[:]" r3 F" m7 e0 F0 r* |
}7 S! M" _ R) O
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值
func (pow *ProofOfWork)Mine()(uint64,[]byte) {. S k. S, I5 N
var nonce uint646 v( Z$ L; W, V
//nonce从0开始穷举,直到出现哈希值小于给到的目标值! I& L k; x7 U
var hash []byte8 x' C) z V0 D4 J' q
for {+ h" X3 ?5 T# H- C& Q5 q4 [
hash=pow.PreparetoMine(nonce)
var hashint big.Int
hashint.SetBytes(hash)
//对比哈希值是否小于目标值,小于则成功退出8 o% j0 e2 T) X) v& ~8 K
if hashint.Cmp(pow.target)==-1 {! _: k7 t1 C6 C8 u
break
}2 `3 N: D8 m- I2 \, n" A% G4 \9 E
//不小于则继续穷举$ y H) Z, J s, _) v+ P
nonce++
}) N+ D5 v# v" m2 k- x8 f+ J8 z
return nonce,hash' b2 p7 V. L: p+ v5 [
}
//调用
func main() {
bc:=NewblockChain()- ]0 t( {! c; Z& S6 O7 z
bc.Addblock([]byte("welcometo"))9 m* b4 Y/ E6 g7 J% l J8 l, y
bc.Addblock([]byte("mycsdnblog"))7 a4 H5 N0 a0 f$ H
bc.PrintAll()% G# }4 I. A- S7 x8 \- i* R L0 v' R
}0 d; K7 I1 L$ K5 ^2 v" X
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
猜你喜欢
成为第一个吐槽的人