Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。
; `2 b9 K3 k: e8 @% c2 _代码分析
4 ?6 V. v+ s9 i. s+ j1 F& d) {9 z三大模块
# l, q. S' m8 x0 w  Q" s7 I代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。. J. c* p0 z$ g* c
运行流程. y! o% u( E) y% \4 W9 [( b5 Y
首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。
. t- {) j4 I: m2 z接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
1 P8 G, U2 R# y0 Y# ^- l$ b' A然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。3 G) t- ^+ {' b$ g8 @3 Q
有了大概的运行流程接下来再来看代码就会轻松很多了。( H2 D0 ~( g3 m% w- T
package main4 f0 s8 I" T4 z! ]* r
import (
" i% C; n: `! b3 r) D$ m5 w! ~        "math/big"
+ d8 @+ H" o. R$ r+ {" K: F        "bytes"& [; L) [. a; U& h+ c
        "encoding/binary"# U9 R( T" L" C, T% ?: E
        "crypto/sha256", w/ q% m  P4 J5 e; Q7 K
        "fmt"
% `  |& y' I# p& U        "time"
, ^* r7 P: x9 y+ v* D# r6 N+ h0 c)
7 G5 Y* l5 L& B. a2 y2 @//Block模块
+ o( B+ s% T1 u; x4 ~2 ktype Block struct {
* S+ G1 v) G" ^& y        Version uint64                //版本号
, v. ^  i- B$ G* \) s7 v2 {4 F7 |        MerkelRoot []byte        //这是一个默克尔数,这里先默认为空
, g+ h2 @/ x6 [/ d; P7 z        TimeStamp string         //时间戳
% K9 B9 N; V# ~4 @        Difficulty uint64        //难度值: b& f9 v# `9 I' Q4 i
        Nonce uint64                //挖矿所找到的随机数% t2 B; O( Z& @
        PrevBlockHash []byte//前区块哈希值
8 N6 \# i- Y" Z, ?4 Q        Data []byte                        //插入的数据: g+ }# i" a5 W) B1 \/ O
        Hash []byte                        //当前区块哈希值! i& j  W0 m8 a' A' u
}
3 e  M; q4 H) z* }//给到一个创建新区块的方法
" S# A' P" K: b3 `4 ~/ ^2 O8 r8 r3 pfunc newBlock(data,prehash []byte)*Block  {$ B! q5 L( r" n0 V7 J# V9 v4 K
        block:=Block{; V. x1 g; H% L% \9 R6 z
                Version:00,; i/ |. m& p% L) `/ K1 a! B+ L3 V
                MerkelRoot:[]byte{},
' O/ t7 x4 ^) u8 V; Q                TimeStamp:time.Now().Format("2006-15:04:05"),: J  }) P- O5 D' Q' ]( e; X' r
                Difficulty:difficulty,- a3 ^: l, X; Z" g+ l; N& }
                Data:data,
. n: \  I" H/ }# W                PrevBlockHash:prehash,
  @. n+ r# K2 y6 g+ H% |+ \$ r        }
; Y* i0 Q: F. E/ |! j        //需要被挖矿之后才能创建区块,所以调用挖矿函数( N3 G: H6 F* Y" U
        pow:=NewPOW(&block): p6 |8 s% W% Z, u9 o
        nonce,hash:=pow.Mine()0 M8 ]- [$ T, k8 z( Y) x
        //挖矿结束,得到哈希碰撞值
/ ^# X) x. y$ d) P, {        block.Nonce=nonce' M  `1 r, f9 `9 z
        block.Hash=hash( a0 d5 Z" K) b: K7 l1 c* ?2 k
        return &block- k! u2 Z1 N3 ?/ l  D5 |# Q5 O6 t7 K
}/ H0 C0 e' X8 i# k+ E3 V5 G
//Blockchain模块. I# }. A" d' @6 J9 b% e( J
const gnnesinfo="1996年9月2日,一代伟人诞生了" # S; F1 C- ?% E
//给到一个区块链结构) q& A+ E& z& H: T- l8 A
type Blockchain struct {
0 v. l. V; Q( Z1 X3 a) y7 Y        blocks []*Block5 n9 V( u' S6 G+ J; j
}
) ]; f$ z! [9 O: o2 ^4 l/ V, V//将创世区块加入区块链,并返回一条可供操作的区块链
  ?% Q+ m: a2 _% O! H; Dfunc NewblockChain()*Blockchain  {' O) l3 e7 M& g9 U* {  s
        var bc Blockchain
4 p$ x8 W; T9 \. b! S- C# ~4 Q1 X/ U        block:=newBlock([]byte(gnnesinfo),[]byte{})0 Q+ p! p: K) ^/ x8 [" v. \
        bc.blocks=append(bc.blocks,block)
3 [  G0 h1 d- q        return &bc
! u% s3 X) t5 {1 \! ?/ p& ~" ~9 l}! D6 w$ U0 ?! ?" t
//给到一个增加区块的方法1 k: x6 }1 w2 L0 f1 S+ v) M+ P8 v
func (this *Blockchain)Addblock(data []byte)  {
/ q) i6 w: D7 X! G0 I                lastblockhash:=this.blocks[len(this.blocks)-1].Hash6 l( N2 p$ S  ?" D
                block:=newBlock(data,lastblockhash)0 K" T0 T/ ?8 g8 ^3 B  C2 m# Y
                this.blocks=append(this.blocks,block)
/ v1 M+ P% j& h5 w+ b+ o& t; E}
$ c; Z0 }2 K% T1 s9 ]3 i3 b# N//遍历,打印所有
1 |/ k6 k( c! ?% W) g. [func (this *Blockchain)PrintAll()  {- R" t& [8 m4 W" A3 N
        for i,v:=range this.blocks {
8 D3 M$ s7 [/ p/ z0 d9 H3 }# S                fmt.Printf("=========区块高度%d=========\n",i)  {: [8 r8 ~/ ~# u
                fmt.Printf("Version : %d\n", v.Version); i. l! y; V6 \# b) w+ d/ R# x1 C$ }
                fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
: {& I: n6 @3 E0 V( y                fmt.Printf("Hash : %x\n", v.Hash)
1 s# J" k8 E, T8 U+ q                fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)6 E5 W! q5 k' k
                fmt.Printf("TimeStamp : %s\n", v.TimeStamp)" @0 D6 @# u* p. D+ `& z
                fmt.Printf("Difficuty : %d\n", v.Difficulty)1 y, e3 i2 l+ D. O
                fmt.Printf("Nonce : %d\n", v.Nonce)7 o0 v; S- d1 m9 K6 M% P
                fmt.Printf("Data : %s\n", v.Data)
8 f- W2 h0 q5 Q- G6 V8 N7 x/ t+ E        }
& l( d/ P8 i$ a* z! o}
3 @2 V! }1 v1 _" s3 q; U& `' m//pow挖矿模块) K! @/ @8 C. P8 C
const difficulty=24: o' y4 b" ]$ z% Q. F& l& X
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字
# c: Q9 k) l0 r5 d3 b/ L- x+ S6 Btype ProofOfWork struct {' M' s& A" k$ M/ z9 U
        target *big.Int  f+ u7 ^0 e! ^
        block *Block
0 J  O5 X0 E: _  ^+ X}. `+ q' l7 I# o( j, v. M) A. z
//给到一个根据难度值得到哈希碰撞目标值的函数
5 ~) N: I1 S  N! kfunc Gettargetint()*big.Int  {
) y% \1 k' D: D- W! t        targetint:=big.NewInt(1)3 F/ s* i$ ]/ W! D: R0 J2 c
        targetint.Lsh(targetint,256-difficulty)
) Z. d6 ]. i+ ^5 z5 E4 v2 I        return targetint; t6 A' O% `+ A
}
- C* ?! j' d$ q2 B" V5 T) V' ^# w//创建挖矿的方法
/ b; [5 R' u. q7 @8 S9 `func NewPOW(block *Block)*ProofOfWork  {' E+ P0 H  h7 I. u) b6 _1 r
        var this ProofOfWork
' g: H( V) _% W  l        this.block=block, T: q2 O5 k# V+ K& z( \
        targetint:=Gettargetint()
* o" E% D0 k0 G, w8 h: D        this.target=targetint( ]$ u+ `9 H& h, w( {/ K  S
        return &this
) @8 o' e6 v- b}% h! u+ L5 ], h( g
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化6 j4 S+ B- z. i8 z0 a: D" B
func uint2byte(num uint64)[]byte  {$ o+ J# f5 ]" B' y; s7 @- g
        var buff bytes.Buffer
, u( F: U/ [: C' q        binary.Write(&buff,binary.BigEndian,&num)  _7 \8 S# ~# ~. t
        return buff.Bytes()# o% E' X6 L! \. ?5 f
}
' Y* n0 I" _( s" V$ }6 n* E9 M0 T//挖矿的准备工作,将其他字符组合起来之后求其哈希值7 j% o& e% o5 ^5 U' J
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {# N! @; r* j" x0 A+ e3 V" q
        info:=[][]byte{) u  G3 |! t0 o" V8 d
                pow.block.PrevBlockHash,
7 D7 }' }4 P# b0 c3 B6 K                pow.block.Data,: z! R' W5 S% w
                uint2byte(nonce),( c5 T/ {: w$ s; j8 X
                uint2byte(pow.block.Version),5 e3 p$ |! ^% C+ L- v* |6 u
                uint2byte(pow.block.Difficulty),) J( F- a6 A7 N+ W9 d6 _" `
                []byte(pow.block.TimeStamp),
3 o: v# J6 A7 u9 f1 S+ M9 Q                pow.block.MerkelRoot,
9 q9 y& y* [- K8 n  R        }
  Z4 t6 t$ f# A5 M9 o        allinfo:=bytes.Join(info,[]byte{})5 e: R7 Y; b- N/ ^, b9 @
        hash:=sha256.Sum256(allinfo)
1 a5 f- h. J  ^$ w        return hash[:]
4 M; F8 U2 B( ~$ w8 z/ d}& a1 M/ E; b; E: b( H4 H
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值1 X' n: U# ]3 _  [
func (pow *ProofOfWork)Mine()(uint64,[]byte)  {$ y7 t) M* h( r, j  h" V
        var nonce uint64
, ~* g# D1 {) ^" ?! R1 M7 P+ K3 z        //nonce从0开始穷举,直到出现哈希值小于给到的目标值+ Z& I/ i8 D5 H0 M2 m- Y. m, U% B
        var hash []byte
" C  G5 m5 j: N& \        for  {: h' Y) \* }# Z4 u+ t
                hash=pow.PreparetoMine(nonce)
) I- d$ o) X2 _% S) l: N+ e                var hashint big.Int
% F/ l! ^3 N& K# G2 _; r" s                hashint.SetBytes(hash). i! B3 V6 e% h: ]/ S% C( s
                //对比哈希值是否小于目标值,小于则成功退出
+ u7 L" N9 m) `% ~; c" x$ N0 e                if hashint.Cmp(pow.target)==-1 {
4 V% Q7 n" Y; c7 R# j  a                        break
5 u& S* N+ W( `/ t+ r6 c4 d                }
' I9 K. C: e$ `                //不小于则继续穷举
$ j" z( [2 E  u; |                nonce++5 F  A* a2 g9 h$ i8 Z# j- V4 P
        }2 p; n3 l8 q( `, k- H! T
        return nonce,hash
3 q6 d7 m* I1 p; [0 d6 H# s* `" E}
! t& x( a! l' n4 d4 E//调用7 B5 S$ y. _0 ]5 S, w
func main()  {
+ `( t: h" r1 a& N" b/ sbc:=NewblockChain()
/ K& \8 a- L) G% v& |bc.Addblock([]byte("welcometo"))+ v; S3 l" c7 `! f' G
bc.Addblock([]byte("mycsdnblog"))
) j1 J0 n- n; w' Z& `3 @bc.PrintAll()6 w5 G6 [3 z. M  F
}3 \1 v) t! L! C/ T
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10