简单区块链的实现(带POW挖矿系统)
蓝天天使2017
发表于 2022-12-7 11:38:58
166
0
0
代码分析
三大模块5 c0 G6 h0 E) E/ V! F
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
运行流程3 x9 u' a; |! f( c
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。( b) T2 G9 |( G3 j
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。3 E: W+ r& v8 }# {( u6 ?
有了大概的运行流程接下来再来看代码就会轻松很多了。
package main
import (
"math/big"
"bytes"
"encoding/binary"
"crypto/sha256"
"fmt"
"time"" D1 d3 P: `1 f3 q6 d
)
//Block模块: \' N, q& `" w# B* k
type Block struct {& P" b' s) \# M5 I
Version uint64 //版本号& [# {% p3 x+ Q! G% r
MerkelRoot []byte //这是一个默克尔数,这里先默认为空1 M1 ]) X1 H6 R( k6 V
TimeStamp string //时间戳
Difficulty uint64 //难度值
Nonce uint64 //挖矿所找到的随机数
PrevBlockHash []byte//前区块哈希值
Data []byte //插入的数据7 T, ^/ b0 j3 X- ]2 i4 J6 ]- b$ b
Hash []byte //当前区块哈希值
}2 s: P# c6 O6 l I: c
//给到一个创建新区块的方法- d! W# y" W% a7 J
func newBlock(data,prehash []byte)*Block {% [: d7 D9 _' d
block:=Block{
Version:00,
MerkelRoot:[]byte{},1 R( H6 Q# q: [/ ~5 [6 C: c" L
TimeStamp:time.Now().Format("2006-15:04:05"),
Difficulty:difficulty,
Data:data,4 ]4 ~; O9 l* X2 D( ?- t& X! x
PrevBlockHash:prehash,% I: w. n6 Q' Y) e! Z2 ^9 U
}% ^- t5 Q8 k9 t' g; P$ ^- o
//需要被挖矿之后才能创建区块,所以调用挖矿函数( f2 X9 {! m( w" o. A
pow:=NewPOW(&block)- i% d& B. Y( @! w# r& j
nonce,hash:=pow.Mine()
//挖矿结束,得到哈希碰撞值; h0 k. O. n$ `; w3 {9 a
block.Nonce=nonce3 g2 ^3 J/ U {& J; K& S$ J
block.Hash=hash5 ^; N3 h: ^$ r
return &block
}5 E0 g. Q) r2 {5 V; H7 }3 u
//Blockchain模块' d$ L6 V4 N }1 g
const gnnesinfo="1996年9月2日,一代伟人诞生了" & O/ t6 q- _# V( L
//给到一个区块链结构
type Blockchain struct {
blocks []*Block
}
//将创世区块加入区块链,并返回一条可供操作的区块链
func NewblockChain()*Blockchain {: T9 Z0 o+ ~, Y+ z* U" k9 I3 [# v
var bc Blockchain9 L |; W4 I' i$ N* U8 T
block:=newBlock([]byte(gnnesinfo),[]byte{})
bc.blocks=append(bc.blocks,block). i0 `& E6 Y* v* A( E) s
return &bc; ]3 Y l8 q; ]
}% a; z8 a1 W" G& g. [
//给到一个增加区块的方法
func (this *Blockchain)Addblock(data []byte) {
lastblockhash:=this.blocks[len(this.blocks)-1].Hash, c. Z* R2 q7 Y7 b3 Q4 t, b
block:=newBlock(data,lastblockhash)
this.blocks=append(this.blocks,block)# C" H, k% m# g5 `( Y
}0 L: z$ G) t# ^+ }
//遍历,打印所有; a# c% n: a" z8 z" m- @; K
func (this *Blockchain)PrintAll() {0 w- f8 x- s* E" ^6 u) L* X
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)% j4 J2 _8 N4 B: u8 t) D8 V! f
fmt.Printf("TimeStamp : %s\n", v.TimeStamp)0 S& V7 Y# @. L; ?5 D5 g. R+ N% Y
fmt.Printf("Difficuty : %d\n", v.Difficulty)0 ~+ D; F' U4 S* G
fmt.Printf("Nonce : %d\n", v.Nonce)
fmt.Printf("Data : %s\n", v.Data)
}1 i; E' G2 O( V2 T1 Z
}
//pow挖矿模块
const difficulty=24; T8 y" R) I+ ]8 U
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字! h! B- t- O. w. \4 F' B9 o
type ProofOfWork struct {/ M5 f: S) S; ~8 ]/ j) d! O- _
target *big.Int9 l* v, v9 z+ |+ G# O
block *Block P- p% X- g' Y. g* [- Z$ K$ e
}0 @8 r) c5 X8 Q4 g6 N, P
//给到一个根据难度值得到哈希碰撞目标值的函数7 B# i% V1 |& e+ \
func Gettargetint()*big.Int {. ], ~# G5 B) J9 S
targetint:=big.NewInt(1)
targetint.Lsh(targetint,256-difficulty)
return targetint/ j# V2 w) H8 O1 f" r
}
//创建挖矿的方法
func NewPOW(block *Block)*ProofOfWork {! e1 P" y* Z0 ^$ L
var this ProofOfWork
this.block=block3 n5 ]; G0 X- b* Y
targetint:=Gettargetint()8 ?; b% F+ |1 a0 J- p
this.target=targetint
return &this
}% U% b$ q$ |# |8 i$ ^
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化% d2 }' W" A" j; R9 K: }* c
func uint2byte(num uint64)[]byte {
var buff bytes.Buffer
binary.Write(&buff,binary.BigEndian,&num); f+ h" A$ S3 a6 C3 I
return buff.Bytes()
}
//挖矿的准备工作,将其他字符组合起来之后求其哈希值# n$ k# P* l3 \! W, j4 S- G
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
info:=[][]byte{
pow.block.PrevBlockHash,
pow.block.Data,
uint2byte(nonce),; r- W' U6 i, `$ k* @ n
uint2byte(pow.block.Version),. q8 g3 _1 u/ E
uint2byte(pow.block.Difficulty),; Z3 n6 P' d- @3 y0 o/ ]" s9 L
[]byte(pow.block.TimeStamp),8 L$ @% u& V, ?# S1 D
pow.block.MerkelRoot,% `3 @% V" @8 H
}: r3 a) Y$ q! M B
allinfo:=bytes.Join(info,[]byte{})% R2 @* e e" O; Q. w! t
hash:=sha256.Sum256(allinfo)8 G- Z4 t: Y+ v
return hash[:]7 q: N; o; E p m* L# W& G
}
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值
func (pow *ProofOfWork)Mine()(uint64,[]byte) {
var nonce uint64
//nonce从0开始穷举,直到出现哈希值小于给到的目标值! p* R8 {6 L* G: x; b# O
var hash []byte
for {: Q' c: o& I" `
hash=pow.PreparetoMine(nonce)
var hashint big.Int
hashint.SetBytes(hash)
//对比哈希值是否小于目标值,小于则成功退出
if hashint.Cmp(pow.target)==-1 {) P+ q% k( e* W) v, N( C: y
break0 ?" y( }9 _; r' m& x" X$ @
}
//不小于则继续穷举& F( b0 B: ]* X1 T% }
nonce++7 b! m4 O5 m6 }/ A0 x
}
return nonce,hash
}
//调用6 y# ]! l4 c- ^
func main() {
bc:=NewblockChain()6 N- V) o# @( b2 s! s
bc.Addblock([]byte("welcometo")), l5 b( U; E! l; B1 D1 a
bc.Addblock([]byte("mycsdnblog"))
bc.PrintAll()
}4 I/ I9 D$ K% o4 F2 x& J( a
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
猜你喜欢
成为第一个吐槽的人