Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
最火的热词相必就是区块链了,C++和GO是目前最适合区块链开发的两种语言,所以咱们学GO的肯定得学一点区块链的知识,但是区块链涉及太多密码学,金融学、p2p网络等知识了,从哪里切入呢,今天我们就从用go实现一条带有模拟挖矿系统的简单区块链。+ j. b6 o4 ^/ C, ?4 r
代码分析9 X  e6 {$ ?1 {$ r1 H; R
三大模块( u% ]. I' ?1 z2 i; Y9 ?
代码还是比较简单清晰的,主要有三个模块,Block模块、BlockChain模块、POW模块即挖矿模块。# X8 O, T5 D( O* Q( Y0 N
运行流程
) h% Z4 ~: E: _! i1 R) S/ s首先从定义一个区块开始,一个区块中包含的信息有区块信息,时间戳,前区块哈希值,现区块哈希值,经过挖矿后得到的哈希碰撞值等等。2 B7 h; l: c7 ^+ y& Q- n& g7 H$ I  s
接着我们开启一个切片用来存放一个个区块,但是第一个区块是比较特殊的,我们称之为创世区块,在真实的比特币中,第一个区块是由创始人中本聪挖矿所得,没有前哈希值,所以这里我们直接将第一个创世区块创建添加到区块切片中。
. f0 f; t" R9 G% r0 g6 D# W然后给到一个添加区块的方法,用户添加区块信息后,经过POW挖矿系统才能成功添加到区块链上。
( E3 ~6 T; Y- a6 H& s有了大概的运行流程接下来再来看代码就会轻松很多了。! ]" _0 ~0 X- g2 e/ V
package main0 W; |  f% k. p. Y6 t
import (
$ k; O3 H( y% u% g- y        "math/big"
1 i+ U9 t( u( `; v        "bytes"3 L. a  P  ^' ^" [5 Y5 o& ^% b
        "encoding/binary"& R* A% H- A* W% O5 ^1 G% x* R
        "crypto/sha256"
$ V) s- u0 O$ x        "fmt"
* ]: Q. h, j8 M& K1 \: e        "time": @7 G9 K" G. f% p4 r, y
)
1 j+ B2 \% ~. J- B//Block模块- `" s7 x2 M- K7 N. z
type Block struct {
- A) X' y% T6 q, M3 h& F        Version uint64                //版本号! I7 f" z! D" s3 x/ y' d6 I& J
        MerkelRoot []byte        //这是一个默克尔数,这里先默认为空
* j& x  J5 p" T. y, j        TimeStamp string         //时间戳
; t2 i8 ?0 `& y" X( D3 T        Difficulty uint64        //难度值
5 u* P  \, h# s8 N2 f        Nonce uint64                //挖矿所找到的随机数
0 }. L& J/ F% s" @0 V! f. m/ }        PrevBlockHash []byte//前区块哈希值
4 H3 U- S1 E, d( R0 j" e        Data []byte                        //插入的数据5 ^+ U1 X/ Z. f+ ]+ i  Z! ]
        Hash []byte                        //当前区块哈希值
: t' T- u' }6 U% y0 O  i}: Z7 N- A& U* T1 U1 x
//给到一个创建新区块的方法
6 ]6 g9 z1 K4 A4 c4 gfunc newBlock(data,prehash []byte)*Block  {2 u* C9 P& K4 X5 o
        block:=Block{
1 l: R/ M( s9 x/ Q" }8 V                Version:00,
/ d+ Q+ R7 X" V& s; I                MerkelRoot:[]byte{},3 ]; _2 A( ~1 q4 ^
                TimeStamp:time.Now().Format("2006-15:04:05"),% D0 ~1 O- o9 D3 e" @2 y2 j+ j/ ~, o
                Difficulty:difficulty,& S% P5 p1 Y, A" i- A
                Data:data,: i5 z% w' w0 i' u4 n9 _
                PrevBlockHash:prehash,
7 g1 R8 Z8 _* _1 ^% y8 h1 ^' x        }6 {! h' U+ g$ S6 h
        //需要被挖矿之后才能创建区块,所以调用挖矿函数
/ x; {1 R; s$ z        pow:=NewPOW(&block)
6 W1 x, o& C, S" @" W3 {' W, h3 z        nonce,hash:=pow.Mine()
" C: a  B/ Y! \9 B1 L1 G        //挖矿结束,得到哈希碰撞值5 Y0 d: V. x/ @9 o5 u: a$ U. `7 N
        block.Nonce=nonce& K. ?" D! ?- U$ ^
        block.Hash=hash5 O7 L" E% Y/ d4 E* P' t9 o
        return &block
3 B5 R% y( c$ v7 t- f9 T1 U! K}
: N" H1 E/ i# A" N" @0 n//Blockchain模块+ _9 c* }& Y0 F, K0 V
const gnnesinfo="1996年9月2日,一代伟人诞生了" 8 _! Q. {0 a$ p" k  t' u! g8 R
//给到一个区块链结构
1 u- p" z3 N% n8 Q+ Btype Blockchain struct {7 f  r0 Z: m9 T3 B. _/ z
        blocks []*Block% e8 }- ~6 |0 h& C3 [1 `4 x0 w
}6 M$ ~1 j* {  H8 O) F% G
//将创世区块加入区块链,并返回一条可供操作的区块链! n0 ^2 c, s! y; P
func NewblockChain()*Blockchain  {
  J9 o; ~" ^) r1 o7 R, _        var bc Blockchain+ H7 N; F' P' |. w/ m3 T
        block:=newBlock([]byte(gnnesinfo),[]byte{}). X0 J5 n2 I. v% g  x4 h
        bc.blocks=append(bc.blocks,block)4 d4 q' ~/ V4 c! l
        return &bc; S. x, i2 R+ y& w* \8 L
}
& b6 u2 t: r/ f1 C2 h* \5 _& g+ J3 L//给到一个增加区块的方法; m( d3 w0 R8 M9 ^+ v- E
func (this *Blockchain)Addblock(data []byte)  {/ f) x' `/ A. Z6 U
                lastblockhash:=this.blocks[len(this.blocks)-1].Hash7 x) C! Z5 l3 ~: U/ X2 w+ y
                block:=newBlock(data,lastblockhash)2 {* M" C& s- d1 N. ~0 ?
                this.blocks=append(this.blocks,block)8 ^3 w5 q7 v# P% ?+ \' B
}# s+ U- O; c% U. J. P7 }8 R
//遍历,打印所有
" _" }* _, `, R: f  F) [func (this *Blockchain)PrintAll()  {
! X( Z5 {  W- l4 E' a        for i,v:=range this.blocks {
# T; z* l' Y, e7 _( q                fmt.Printf("=========区块高度%d=========\n",i)
' |) `' {, g! b' E+ z* i0 e, i                fmt.Printf("Version : %d\n", v.Version)
7 {- T- q# O' I* r  |$ z                fmt.Printf("PrevBlockHash : %x\n", v.PrevBlockHash)
* q3 i! M* M5 j4 J- Y( P                fmt.Printf("Hash : %x\n", v.Hash)
6 u! Y3 r4 [, F4 D$ f                fmt.Printf("MerkleRoot : %x\n", v.MerkelRoot)
- R4 u' @0 V' s! }7 K; r$ X                fmt.Printf("TimeStamp : %s\n", v.TimeStamp)
) G: E- o6 S* f- d+ ^$ `5 I9 m                fmt.Printf("Difficuty : %d\n", v.Difficulty)8 T& b, e& \0 e3 s+ u: o
                fmt.Printf("Nonce : %d\n", v.Nonce)7 [/ [  {$ B7 R+ ~
                fmt.Printf("Data : %s\n", v.Data)
, k8 f( J' W; S( J" |; V6 k        }
8 E& g2 G: `' S8 p0 ]/ e}# Q2 [, L/ c" M; v6 x$ x9 ^* S" |: @
//pow挖矿模块
$ D- t. D) h5 X/ @- R3 gconst difficulty=24, R4 l: {/ P! M# R
//POW挖矿结构需要两个参数,一个是所需挖矿的区块,另一个是挖矿成功所需目标数字1 ~! O' O' Y/ I) _6 ]7 G
type ProofOfWork struct {0 {/ v8 Y! S6 u' R2 U3 q& a; L$ S) B! ?
        target *big.Int
+ ?7 k; ]9 w# R" G6 h4 w) H        block *Block
' D& k# P) M, m' [  y8 q, p}
3 u& x' c& y- [8 Y! F/ M//给到一个根据难度值得到哈希碰撞目标值的函数
7 T0 h5 A6 Y) Dfunc Gettargetint()*big.Int  {
% l8 ?- M4 q/ G% ?; @        targetint:=big.NewInt(1)
3 z4 `2 ?9 G# M7 V! v+ @# M        targetint.Lsh(targetint,256-difficulty)
' _- w9 |# ]( m2 \        return targetint, b6 \4 M: ^; _5 U. w8 T1 v
}* k, u1 N5 ]* x  @. G  H
//创建挖矿的方法
/ D3 Y+ p0 l  L- Lfunc NewPOW(block *Block)*ProofOfWork  {) V, L7 ]: Y% b0 M$ l
        var this ProofOfWork
6 ~: Q; ?$ L3 ^( C1 [        this.block=block
6 R+ Q9 ^$ b" W/ K        targetint:=Gettargetint()8 s! j# S: h5 V
        this.target=targetint
6 r. w  g1 }* X4 Q        return &this
3 I; u. p% H' M. }0 y6 Q}, _& e' ^2 I1 h8 c, a6 r
//一个用来将uint64转化为字符切片的小函数,方便接下来的转化
1 D3 F# Z4 f9 p. ]  J/ f1 B! g6 h3 Yfunc uint2byte(num uint64)[]byte  {8 Y; S9 Q1 z2 S3 ^, ^, B% `
        var buff bytes.Buffer8 T* M% u# z, d" M  z1 r8 _
        binary.Write(&buff,binary.BigEndian,&num)
2 c% B6 p5 h  [* T: ?( G" Y2 x3 O3 e        return buff.Bytes()* F/ W% _, s9 A: |
}
* N7 Y2 p3 l$ Z+ B1 g6 K3 h//挖矿的准备工作,将其他字符组合起来之后求其哈希值* S! j0 v0 V7 c1 N
func (pow *ProofOfWork)PreparetoMine(nonce uint64)[]byte {
& Q( h" B8 P- l4 r* r7 B1 ]5 G        info:=[][]byte{% k  ^" o/ y! V, A
                pow.block.PrevBlockHash,
/ L6 U. ^( N7 u) p  h6 A" U                pow.block.Data,  T. |6 W: |, X7 t6 ]1 t' u
                uint2byte(nonce),9 u& Q# S9 @  T3 q5 A
                uint2byte(pow.block.Version),, P9 F  V% J7 r6 _$ q
                uint2byte(pow.block.Difficulty),
% u% t. W. Y2 ?) `                []byte(pow.block.TimeStamp),7 F8 E8 ?! Y7 }
                pow.block.MerkelRoot,9 u. J% T6 l3 R
        }
7 w+ n* Z4 n2 M2 b+ f        allinfo:=bytes.Join(info,[]byte{})
5 `+ G+ X9 T# N/ R' |  l2 G        hash:=sha256.Sum256(allinfo)
" g4 W/ O, x) z2 Q% P" a        return hash[:]
5 U0 e  Z" ?+ Q( x0 y}( w2 g3 m! b8 ^  l( s* [5 ^" ~
//pow挖矿方法,返回两个参数,一个是碰撞成功的数字nonce,另一个是当前区块哈希值& r" l7 _+ z' `- ?# ]$ m
func (pow *ProofOfWork)Mine()(uint64,[]byte)  {& N* Z, k, o- A4 O
        var nonce uint64* M6 R# |! l2 p6 Q6 q& I5 `
        //nonce从0开始穷举,直到出现哈希值小于给到的目标值  \0 x' Z: ?& v; c# Y% z. _
        var hash []byte
: W  E* @6 [5 d        for  {
# O  w1 }( I0 o' S" R* W7 U                hash=pow.PreparetoMine(nonce)
7 k: M5 F' h% d" L                var hashint big.Int; e) h$ k' i3 @
                hashint.SetBytes(hash)
, |. c( ~! x, W' m, t                //对比哈希值是否小于目标值,小于则成功退出
6 X: A1 l* D8 l( J/ C9 `                if hashint.Cmp(pow.target)==-1 {6 ~: ~9 a; X: q1 F0 g1 O
                        break
/ I0 u2 H/ n* Z5 X* T3 x                }
- Q; P" I; v) o9 x/ k; r1 A                //不小于则继续穷举( k+ ^2 ]" u5 Y' V# l3 {" I2 ^
                nonce++$ t! C) J5 n+ X' S
        }- N5 O% a4 K5 z/ C8 _: A
        return nonce,hash
' Z3 c) [1 [* q}( \- O2 w. t$ X6 e. H2 o0 G8 F
//调用$ K" X$ l. ?% N
func main()  {# G% p2 h( E+ A
bc:=NewblockChain()
5 l8 X! G3 l: Abc.Addblock([]byte("welcometo"))0 M& h4 _# i8 X7 b& Q3 X, I8 |
bc.Addblock([]byte("mycsdnblog"))& Y* p* |2 h! s2 n
bc.PrintAll()
+ T9 L3 s( h2 X- s* U}" x3 A1 a: l" L5 q
以上就是一个微型的区块链了,虽然看起来很简单,但是对于理解比特币、区块链还是有不少帮助的。
标签: Pow
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

蓝天天使2017 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10