简单区块链的实现(带POW挖矿系统)
蓝天天使2017
发表于 2022-12-7 11:38:58
138
0
0
代码分析+ ]2 D5 @! e/ U' V5 ?1 _. _( k
三大模块2 _* p) D4 R3 X# J0 \- A0 ?
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
运行流程
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。0 W. p2 ]6 Z* O" B
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。3 S* y. f6 s7 |$ b' V
有了大概的运行流程接下来再来看代码就会轻松很多了。/ W6 d7 X; ~: o# \
package main) D5 m2 P: F& F3 J+ |! C1 B4 }
import (8 U( ?$ g# w% h6 Z( o3 T
"math/big"
"bytes"
"encoding/binary"
"crypto/sha256"* ?; w0 J( P, F$ l& n, x6 }# \
"fmt"
"time", V. M% J$ H! C+ i
). p. i+ r- I/ I* l1 u7 p
//Block模块
type Block struct {
Version uint64 //版本号' g. P+ O! t8 F" l( r- L
MerkelRoot []byte //这是一个默克尔数,这里先默认为空
TimeStamp string //时间戳
Difficulty uint64 //难度值' E2 G! D4 y0 r6 }$ p
Nonce uint64 //挖矿所找到的随机数) a% ~) }1 D3 E: S
PrevBlockHash []byte//前区块哈希值
Data []byte //插入的数据
Hash []byte //当前区块哈希值3 `1 Q* N4 m: R
}3 e j7 ~' n9 n( w) x. ^' V* E, q
//给到一个创建新区块的方法
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,
}/ S: J. e) m6 `6 W: v% \- m; ]* L
//需要被挖矿之后才能创建区块,所以调用挖矿函数9 f$ }2 C$ U. y8 |0 ]% X) f0 O
pow:=NewPOW(&block)
nonce,hash:=pow.Mine()
//挖矿结束,得到哈希碰撞值
block.Nonce=nonce, P! P k4 j' Y& ^4 p1 D
block.Hash=hash
return &block) C3 X2 q" @5 N) C ?! Y2 P
}) w' R7 ]7 o5 U1 v. L1 ~3 y
//Blockchain模块 C# J# d: j/ u' L" Y1 ~
const gnnesinfo="1996年9月2日,一代伟人诞生了"
//给到一个区块链结构+ @0 k3 i+ \! U
type Blockchain struct {& p! g" p$ C8 D6 {1 X3 R, p
blocks []*Block9 P) @8 g9 X5 h( E+ x
}
//将创世区块加入区块链,并返回一条可供操作的区块链
func NewblockChain()*Blockchain {
var bc Blockchain
block:=newBlock([]byte(gnnesinfo),[]byte{})
bc.blocks=append(bc.blocks,block)
return &bc* m" S+ s+ v4 l% G4 T
}
//给到一个增加区块的方法
func (this *Blockchain)Addblock(data []byte) {! B- |4 j# A; _& r
lastblockhash:=this.blocks[len(this.blocks)-1].Hash% h3 m; h. G: K( c' u/ r( p4 o
block:=newBlock(data,lastblockhash)
this.blocks=append(this.blocks,block)1 J8 j% O- c, x1 Z" \. d
}( H n" M+ W0 C. D0 A# Y
//遍历,打印所有
func (this *Blockchain)PrintAll() {
for i,v:=range this.blocks {
fmt.Printf("=========区块高度%d=========\n",i)
fmt.Printf("Version : %d\n", v.Version)) r" w: U8 i) V& p. K
fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)# s' g$ l; O" b! c5 u
fmt.Printf("Hash : %x\n", v.Hash)
fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)
fmt.Printf("TimeStamp : %s\n", v.TimeStamp), n- c( T* } b* ~ M
fmt.Printf("Difficuty : %d\n", v.Difficulty)+ c# s0 O0 M6 S
fmt.Printf("Nonce : %d\n", v.Nonce)( _4 X4 M5 ^& T- D2 a5 v, g
fmt.Printf("Data : %s\n", v.Data)5 }, k: M7 n* J( y% @
}
}& R: {0 Y9 b# y) \/ d8 Z( T
//pow挖矿模块
const difficulty=240 D+ F9 @/ T A' m% M V' b: z
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
type ProofOfWork struct {, ~& h" Y# ~8 ]9 T
target *big.Int0 n. T1 I4 [' w" z. |8 q. z
block *Block1 }4 i# B& C' \5 h
}
//给到一个根据难度值得到哈希碰撞目标值的函数
func Gettargetint()*big.Int {
targetint:=big.NewInt(1)
targetint.Lsh(targetint,256-difficulty)
return targetint
}+ d: w6 u( U u J
//创建挖矿的方法
func NewPOW(block *Block)*ProofOfWork {
var this ProofOfWork9 Y3 A8 u7 n2 w2 O9 g
this.block=block
targetint:=Gettargetint()# d$ D2 `2 y# V# j6 m
this.target=targetint
return &this
}
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化
func uint2byte(num uint64)[]byte {
var buff bytes.Buffer
binary.Write(&buff,binary.BigEndian,&num) {# D/ O ^+ @, i
return buff.Bytes()+ U* a7 |9 p" R' j S: m# s9 b
}
//挖矿的准备工作,将其他字符组合起来之后求其哈希值6 I+ O( A' A3 y1 {: R
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
info:=[][]byte{4 ]; b/ ]3 ?2 D) ?
pow.block.PrevBlockHash,! P) ?0 _( @, s6 s8 m
pow.block.Data,* l3 g( T! q0 Y
uint2byte(nonce),
uint2byte(pow.block.Version),$ V: m- ]( O( s; |- Y
uint2byte(pow.block.Difficulty),& [8 J7 {$ u$ A1 V% D
[]byte(pow.block.TimeStamp),
pow.block.MerkelRoot, o O! _# E/ j
}
allinfo:=bytes.Join(info,[]byte{}), o6 v- y, B- Y, {
hash:=sha256.Sum256(allinfo)
return hash[:]% K+ T# ~- Y7 V2 n+ |* i
}6 D5 z' B$ N$ E& _5 k, ~+ P+ M
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值; Y) p5 `1 c+ e" Q8 ]8 {* p( O" o* @
func (pow *ProofOfWork)Mine()(uint64,[]byte) {
var nonce uint64
//nonce从0开始穷举,直到出现哈希值小于给到的目标值
var hash []byte
for {
hash=pow.PreparetoMine(nonce)" A! }% `, P, T4 x
var hashint big.Int2 C7 L" D* X: {( {5 W7 t0 S3 [' K
hashint.SetBytes(hash)( T! T# P3 _ y' s( k" i
//对比哈希值是否小于目标值,小于则成功退出
if hashint.Cmp(pow.target)==-1 {, n& n* S! A% `& M! y ~9 e
break3 ]+ B$ m& ?7 g3 S
}
//不小于则继续穷举
nonce++9 g! x% l1 z* H3 D
}
return nonce,hash" f( [: t+ c8 @5 q9 O
}' C4 o* S8 B2 w+ q
//调用# l- S2 E8 N5 o+ I/ k
func main() {
bc:=NewblockChain()
bc.Addblock([]byte("welcometo"))
bc.Addblock([]byte("mycsdnblog"))( A8 g4 u! T' Q$ h+ Z/ B" _! W
bc.PrintAll()) O5 U7 e0 U7 |" n8 x# J: t
}9 i, d8 P+ R) I/ ?+ f
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
猜你喜欢
成为第一个吐槽的人