Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。4 M# D- n9 ^+ E4 P/ T2 N- I
代码分析+ ]2 D5 @! e/ U' V5 ?1 _. _( k
三大模块2 _* p) D4 R3 X# J0 \- A0 ?
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
8 W9 x% ^$ Z% H; u5 J9 w# j运行流程
& H( r: v. e  t' x首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
- }5 Z- A$ M/ e' j5 [/ [接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。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"
* l6 K8 S3 I2 i: a4 e2 s( H9 \1 j        "bytes"
3 N* e& y* ?! }8 o( L; U9 l1 B5 e        "encoding/binary"
2 N  @! f9 U; M, q  |$ e        "crypto/sha256"* ?; w0 J( P, F$ l& n, x6 }# \
        "fmt"
! V3 H! X1 B0 c" b        "time", V. M% J$ H! C+ i
). p. i+ r- I/ I* l1 u7 p
//Block模块
) K+ ]% k! S7 }; [; ]1 Atype Block struct {
4 d. `/ w% k- ?; a/ ?/ f- g6 f7 {        Version uint64                //版本号' g. P+ O! t8 F" l( r- L
        MerkelRoot []byte        //这是一个默克尔数,这里先默认为空
6 l$ p: t, y: k$ o        TimeStamp string         //时间戳
* `9 S% C+ K6 O8 P8 E        Difficulty uint64        //难度值' E2 G! D4 y0 r6 }$ p
        Nonce uint64                //挖矿所找到的随机数) a% ~) }1 D3 E: S
        PrevBlockHash []byte//前区块哈希值
! K/ k( ^  V* @, Z6 E        Data []byte                        //插入的数据
: B: X1 {' b9 Q1 A        Hash []byte                        //当前区块哈希值3 `1 Q* N4 m: R
}3 e  j7 ~' n9 n( w) x. ^' V* E, q
//给到一个创建新区块的方法
7 L" Z( @/ k$ v, R0 yfunc newBlock(data,prehash []byte)*Block  {
6 [; U% [1 G& M; y        block:=Block{
8 n. B: I% \0 H8 a% B                Version:00,
, y- I; w& i8 P" o" o4 @                MerkelRoot:[]byte{},
1 ^: n" v% {; x: d% L+ d                TimeStamp:time.Now().Format("2006-15:04:05"),
! ~- S$ @& U8 _7 f                Difficulty:difficulty,
( h$ \: Y3 T1 }# M1 _                Data:data,
/ r' t5 t9 J# \                PrevBlockHash:prehash,
# }' x& j$ o8 d        }/ S: J. e) m6 `6 W: v% \- m; ]* L
        //需要被挖矿之后才能创建区块,所以调用挖矿函数9 f$ }2 C$ U. y8 |0 ]% X) f0 O
        pow:=NewPOW(&block)
- Z5 N$ W% N; V5 i, w, x4 v        nonce,hash:=pow.Mine()
* L& e3 G1 k) @( b        //挖矿结束,得到哈希碰撞值
  \- L& P/ K1 ~% B5 x" t2 C        block.Nonce=nonce, P! P  k4 j' Y& ^4 p1 D
        block.Hash=hash
9 N' V+ g8 g5 w! Z5 G) P        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日,一代伟人诞生了"
! P$ K8 v& u; X2 T+ V& C( ^//给到一个区块链结构+ @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
}
+ X5 q# Y0 y  [) r  l//将创世区块加入区块链,并返回一条可供操作的区块链
3 D7 N7 a8 P2 \4 Y) ofunc NewblockChain()*Blockchain  {
/ o7 G! R+ G3 P5 k- A- p        var bc Blockchain
, n$ }' m* z& [        block:=newBlock([]byte(gnnesinfo),[]byte{})
# h5 W" p7 x7 J# J8 [        bc.blocks=append(bc.blocks,block)
3 n4 x! ]3 C" y- @        return &bc* m" S+ s+ v4 l% G4 T
}
" L1 X, l& t. q//给到一个增加区块的方法
9 f4 i' \  }1 b  }( Xfunc (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)
2 d) ]" w9 f, b. @/ E                this.blocks=append(this.blocks,block)1 J8 j% O- c, x1 Z" \. d
}( H  n" M+ W0 C. D0 A# Y
//遍历,打印所有
2 v; ^$ O6 I  _9 C5 l- I9 @, Zfunc (this *Blockchain)PrintAll()  {
) J" z  u, `5 y0 v+ Z5 f1 [        for i,v:=range this.blocks {
) S2 @. u0 |+ E+ N                fmt.Printf("=========区块高度%d=========\n",i)
4 a$ f9 _2 y# K. q4 R! B' L                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)
1 A* M9 t; l; N+ B                fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)
% F+ t# C$ f/ b& a! Y                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% @
        }
  z. K; P7 I5 C7 f, g, A}& R: {0 Y9 b# y) \/ d8 Z( T
//pow挖矿模块
' C% O/ ~9 I+ @/ C+ Q. Oconst difficulty=240 D+ F9 @/ T  A' m% M  V' b: z
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
$ u  o, g' m  {0 m* \/ Mtype 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
}
: [! x7 }' P  p) p: N$ `. Z//给到一个根据难度值得到哈希碰撞目标值的函数
) n+ `: s9 \5 j. X. m8 Nfunc Gettargetint()*big.Int  {
, n  I( w( P! Q# b- u: p+ f, `$ }        targetint:=big.NewInt(1)
2 F$ x; n* g/ g7 F$ N( h        targetint.Lsh(targetint,256-difficulty)
, b- z$ b; z1 l2 `3 [3 r* h% K        return targetint
# e, S" \, f3 L$ p% I. Q/ {5 B}+ d: w6 u( U  u  J
//创建挖矿的方法
2 s' T& ^. L% ]  \0 W7 xfunc NewPOW(block *Block)*ProofOfWork  {
$ [! J' O" {4 W5 m1 S7 E        var this ProofOfWork9 Y3 A8 u7 n2 w2 O9 g
        this.block=block
7 E) ?1 E! S& v" [) V) Y        targetint:=Gettargetint()# d$ D2 `2 y# V# j6 m
        this.target=targetint
, [' A  k- a) H% v6 c        return &this
9 ?* L4 X! _* X* |( u}
  @7 v8 I& Y4 |* s  W/ H1 w//一个用来将uint64转化为字符切片的小函数,方便接下来的转化
2 s) z- B' [3 W+ `7 V! I" _% lfunc uint2byte(num uint64)[]byte  {
* \" {1 k/ {7 ?7 R! y6 z. F        var buff bytes.Buffer
0 M7 X% l& h+ d1 J" m5 h0 A( H        binary.Write(&buff,binary.BigEndian,&num)  {# D/ O  ^+ @, i
        return buff.Bytes()+ U* a7 |9 p" R' j  S: m# s9 b
}
9 {" l5 Y- j9 L& O+ L4 V0 E. R//挖矿的准备工作,将其他字符组合起来之后求其哈希值6 I+ O( A' A3 y1 {: R
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
" R( q% n$ q6 m9 _) Y        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),
' w& A1 ~" h7 ^" r6 f                uint2byte(pow.block.Version),$ V: m- ]( O( s; |- Y
                uint2byte(pow.block.Difficulty),& [8 J7 {$ u$ A1 V% D
                []byte(pow.block.TimeStamp),
9 f7 C# \* q6 g) [+ S4 M                pow.block.MerkelRoot,  o  O! _# E/ j
        }
' h- m: e% v: [. K1 x        allinfo:=bytes.Join(info,[]byte{}), o6 v- y, B- Y, {
        hash:=sha256.Sum256(allinfo)
: E( N3 V# k  W: b0 S" L9 c        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)  {
: C3 m2 {9 u/ t; Q  [6 y* U6 d2 j        var nonce uint64
  W3 l' k2 s' b- v        //nonce从0开始穷举,直到出现哈希值小于给到的目标值
* @" s) m; t. }# m0 l        var hash []byte
9 e* [6 E, q7 D        for  {
1 d# Q1 \' {+ j1 M                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
                //对比哈希值是否小于目标值,小于则成功退出
. y4 x" }+ b( n                if hashint.Cmp(pow.target)==-1 {, n& n* S! A% `& M! y  ~9 e
                        break3 ]+ B$ m& ?7 g3 S
                }
0 \# H+ J$ i( B# S3 O: k7 L                //不小于则继续穷举
! Y9 ]' e6 k! o2 h  _7 P3 k                nonce++9 g! x% l1 z* H3 D
        }
- R- g% f* l7 k6 P! Q$ ]* t9 m9 f3 ~        return nonce,hash" f( [: t+ c8 @5 q9 O
}' C4 o* S8 B2 w+ q
//调用# l- S2 E8 N5 o+ I/ k
func main()  {
' R# i( M) |/ C  {( z3 abc:=NewblockChain()
) c; D4 ~8 T6 Z6 Nbc.Addblock([]byte("welcometo"))
4 Z: _1 D5 r: r: L$ ]  F! Gbc.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
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10