Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。
* y5 y# B8 D; R  _9 a! a* s代码分析
: O: C: p' w* Y, m- _  g三大模块5 c0 G6 h0 E) E/ V! F
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。
4 f  t2 h, y2 j运行流程3 x9 u' a; |! f( c
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。( b) T2 G9 |( G3 j
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
2 G1 a0 }) u. J' W; Z. Q然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。3 E: W+ r& v8 }# {( u6 ?
有了大概的运行流程接下来再来看代码就会轻松很多了。
/ g: `. A8 R* W. Y% b" ypackage main
7 m5 ^8 N% X; w; _4 d  Bimport (
+ B7 Q3 w3 a; w. S        "math/big"
: ?9 G( s; V4 M: T        "bytes"
0 p5 X4 M/ e, l' z        "encoding/binary"
! M3 e- \7 a' D# m9 \2 I        "crypto/sha256"
$ q" }0 J2 V2 V+ W6 j: t" Z        "fmt"
* L- C! T3 t  ~( v9 Y        "time"" D1 d3 P: `1 f3 q6 d
)
, R: s% _) V) U//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         //时间戳
% k3 ?6 i( p& o& |& a7 r        Difficulty uint64        //难度值
4 q7 B) S6 k! R8 I; j        Nonce uint64                //挖矿所找到的随机数
- m- G  k0 u1 {7 C8 I        PrevBlockHash []byte//前区块哈希值
8 L- S6 y! Q) e: ~; ~0 Q# k        Data []byte                        //插入的数据7 T, ^/ b0 j3 X- ]2 i4 J6 ]- b$ b
        Hash []byte                        //当前区块哈希值
. ~6 u  [8 G" z2 o6 P1 p- R}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{
! Z2 O" l+ s+ B                Version:00,
9 F/ y7 Q8 i' h- D1 |# T. L: J                MerkelRoot:[]byte{},1 R( H6 Q# q: [/ ~5 [6 C: c" L
                TimeStamp:time.Now().Format("2006-15:04:05"),
# f4 D6 s0 Z4 a                Difficulty:difficulty,
+ V" c' _: h3 Z* e# R                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()
0 i) L, T. J6 z8 j# y) B1 |! b3 M: P$ p        //挖矿结束,得到哈希碰撞值; 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
4 C  C3 V  T! I+ f}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
//给到一个区块链结构
9 w7 I' H+ K& o6 Vtype Blockchain struct {
& x* `0 m$ f+ w) ~! L( z3 y        blocks []*Block
$ J" Q$ w, p% a' J- o4 X}
, T$ ^0 K3 k- x, k5 i/ y3 k5 V$ }6 w//将创世区块加入区块链,并返回一条可供操作的区块链
" j5 n+ x7 v8 L7 z! T/ M" @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{})
/ O% a9 O) }9 }- l        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. [
//给到一个增加区块的方法
6 Q' K& }3 F$ I# |  nfunc (this *Blockchain)Addblock(data []byte)  {
9 w; P% m6 O+ u/ F4 t                lastblockhash:=this.blocks[len(this.blocks)-1].Hash, c. Z* R2 q7 Y7 b3 Q4 t, b
                block:=newBlock(data,lastblockhash)
6 u5 a$ \# e) a+ i; [                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 {
* s- @* K; g7 z                fmt.Printf("=========区块高度%d=========\n",i)
$ ^* c' A6 P9 x* i9 J                fmt.Printf("Version : %d\n", v.Version)
2 D/ K# n) I) P; u& I: i/ ?                fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
+ O# a# M; \$ q  n4 T% T                fmt.Printf("Hash : %x\n", v.Hash)
7 R+ t4 h& O3 a# l                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)
9 z- X6 |2 G  v                fmt.Printf("Data : %s\n", v.Data)
: f: z" c7 F5 s: k        }1 i; E' G2 O( V2 T1 Z
}
8 J0 P- h+ F/ J: @  `3 o; z! |" C//pow挖矿模块
: G4 p5 B+ o' L( |* m7 x# C! lconst 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)
! s! N( w# X0 b/ n& h        targetint.Lsh(targetint,256-difficulty)
  c2 V& w3 G) x: f) A        return targetint/ j# V2 w) H8 O1 f" r
}
3 a% a* b6 O# i& o/ k3 e//创建挖矿的方法
: M) o0 B+ B* y& Xfunc NewPOW(block *Block)*ProofOfWork  {! e1 P" y* Z0 ^$ L
        var this ProofOfWork
& i4 f8 }: [& v# @2 j' j$ x; s6 y        this.block=block3 n5 ]; G0 X- b* Y
        targetint:=Gettargetint()8 ?; b% F+ |1 a0 J- p
        this.target=targetint
: O+ e& v/ b8 e7 c6 `- |; b        return &this
' f; P9 L; Z8 I. F/ }) m* i$ ]" u}% U% b$ q$ |# |8 i$ ^
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化% d2 }' W" A" j; R9 K: }* c
func uint2byte(num uint64)[]byte  {
/ R/ p/ P% d. G6 v+ ~4 u        var buff bytes.Buffer
6 k. w6 M# U/ U- ?* F        binary.Write(&buff,binary.BigEndian,&num); f+ h" A$ S3 a6 C3 I
        return buff.Bytes()
0 \( ~7 |1 v" @  q1 _; A# R}
0 D7 r3 A  g+ Z5 Z+ B2 D5 `//挖矿的准备工作,将其他字符组合起来之后求其哈希值# n$ k# P* l3 \! W, j4 S- G
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
. N" c- e" p% ^* @. L+ h        info:=[][]byte{
  O; P5 E: \2 O2 m+ S                pow.block.PrevBlockHash,
- b! b) Z  S' a& ]$ W                pow.block.Data,
/ U$ s# Q3 h, {                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
}
7 @4 [# X1 G; C) u/ }//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值
1 u! `; y' ~8 e  Y. {func (pow *ProofOfWork)Mine()(uint64,[]byte)  {
9 Z% p- |6 x) n; q; [) t3 U        var nonce uint64
! X- w6 F2 A. `9 u        //nonce从0开始穷举,直到出现哈希值小于给到的目标值! p* R8 {6 L* G: x; b# O
        var hash []byte
. a7 F' l( e2 x6 R% \, w& O7 D        for  {: Q' c: o& I" `
                hash=pow.PreparetoMine(nonce)
4 ^. O6 ?' C$ g5 u                var hashint big.Int
5 _' E- I# E6 k: W+ t                hashint.SetBytes(hash)
8 T" S$ [3 V, K                //对比哈希值是否小于目标值,小于则成功退出
  q) p, p2 R1 s, ]) i$ C5 b                if hashint.Cmp(pow.target)==-1 {) P+ q% k( e* W) v, N( C: y
                        break0 ?" y( }9 _; r' m& x" X$ @
                }
( G# U$ Z: L2 a9 p& s( h/ n7 B& T' g                //不小于则继续穷举& F( b0 B: ]* X1 T% }
                nonce++7 b! m4 O5 m6 }/ A0 x
        }
1 ]; z8 \: c; [& z2 Z% C        return nonce,hash
$ l# ?$ }" w; `' a: u}
2 O% f4 k$ f+ }1 ?0 o//调用6 y# ]! l4 c- ^
func main()  {
8 \, L2 @) ]) f( d- B$ xbc:=NewblockChain()6 N- V) o# @( b2 s! s
bc.Addblock([]byte("welcometo")), l5 b( U; E! l; B1 D1 a
bc.Addblock([]byte("mycsdnblog"))
& }3 }. G% }) T* Cbc.PrintAll()
% |. t# P" W$ G7 f}4 I/ I9 D$ K% o4 F2 x& J( a
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10